﻿using DLL.Net.RJSpeech;
using DLL.NET.DJ.MSDM;
using DLL.NET50.DB.MS.AdviceAndDrug;
using DLL.NET50.SerialPort.MCU.LED;
using DLL.Net60.MotionCtrl.ControlBase;
using DLL.NetStandard.FlushRobot.MS.Entity.Param;
using DLL.Standard.Infrastructure.Log;
using Prism.Events;
using Prism.Services.Dialogs;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace DLL.FlushRobot.MS.Run
{
    public interface IMS_HP_AutoFlush : IMS_HP_RunBase
    {
        bool IsFinished { get; set; }
        IDJ_MS cDJ { get; set; }
        IControlLED cLED { get; set; }
        bool HaveBottleInDevice { get; set; }
        COneRowStation SolventRow { get; set; }
        public float[] RemainDrugDose { get; set; }
        string jobNumber { get; set; }
        int WorkMode { get; set; }

        bool ReadParamFile();

        bool AutoRun();

        long MoveToPutDrugPos();

        long BottleRemainIsZero();

        void ResetRemainDrugDose();

        long Flush_SolventInAndPullInjector(COneRowStation oneRow, int[] validCol, int loopIndex);
    }

    public class CMS_HP_AutoFlush : CMS_HP_RunBase, IMS_HP_AutoFlush
    {
        #region property

        private bool _isFinished = true;

        public bool IsFinished
        {
            get { return _isFinished; }
            set { _isFinished = value; }
        }

        private IDJ_MS _cDJ;

        public IDJ_MS cDJ
        {
            get { return _cDJ; }
            set { _cDJ = value; }
        }

        private IControlLED _cLED;

        public IControlLED cLED
        {
            get { return _cLED; }
            set { _cLED = value; }
        }

        private COneRowStation _SolventRow = new COneRowStation();

        public COneRowStation SolventRow
        {
            get { return _SolventRow; }
            set { _SolventRow = value; }
        }

        private bool _HaveBottleInDevice = false;

        public bool HaveBottleInDevice
        {
            get { return _HaveBottleInDevice; }
            set { _HaveBottleInDevice = value; }
        }

        private float[] _RemainDrugDose = new float[MaxColPointCount];

        public float[] RemainDrugDose
        {
            get { return _RemainDrugDose; }
            set { _RemainDrugDose = value; }
        }

        private string _jobNumber = "";

        public string jobNumber
        {
            get { return _jobNumber; }
            set { _jobNumber = value; }
        }

        private int _WorkMode = 0;

        public int WorkMode
        {
            get { return _WorkMode; }
            set { _WorkMode = value; }
        }

        #endregion property

        #region 控制LED灯he舵机函数

        private DateTime startTime = DateTime.Now;
        private DateTime endTime = DateTime.Now;
        private int usedTime = 0;

        #endregion 控制LED灯he舵机函数

        private IDialogService _dialogService;

        public CMS_HP_AutoFlush(IMotionCtrlBase motion,
            IControlLED controlLED,
            IDJ_MS dJ_MS,
            IDialogService dialogService,
            IEventAggregator eventAggregator
            ) : base(dialogService, eventAggregator)
        {
            cLED = controlLED;
            cDJ = dJ_MS;
            //_bottleInspcet = bottleInspcet;
            _dialogService = dialogService;
            //System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
            //stopwatch.Start(); //  开始监视代码
            nMotionCtrl = motion;
            ReadParamFile();
            //stopwatch.Stop(); //  停止监视
            //TimeSpan timeSpan = stopwatch.Elapsed; //  获取总时间
            //double milliseconds = timeSpan.TotalMilliseconds;  //  毫秒数
            //SetRunState("CMS_AutoFlush intialize used time=" + milliseconds.ToString());
        }

        public bool ReadParamFile()
        {
            //读取参数
            CMS_WR_WorkConfigParam WR_WorkConfig = new CMS_WR_WorkConfigParam();
            WR_WorkConfig.ReadParam();
            base.WorkConfig = WR_WorkConfig.Param;
            CMS_WR_DeviceConfigParam wrdevice = new CMS_WR_DeviceConfigParam();
            wrdevice.ReadParam();
            DeviceConfig = wrdevice.Param;
            CMS_WR_WorkPointParam wrpoint = new CMS_WR_WorkPointParam();
            wrpoint.ReadParam();
            WorkPoint = wrpoint.Param;
            StationColNum = DeviceConfig.StationColNum;
            StationRowNum = DeviceConfig.StationRowNum + 1;
            //cDJ.ReadRunPosParam();
            cLED.ReadComParam();
            axisesSpeed = nMotionCtrl.motionParam.axis.speedParam.axisesSpeed;
            cDJ.DJCtrl.ReadRunPosParam();
            cDJ.OpenJawMode = base.WorkConfig.OpenjawMode;
            cDJ.EnableBottleJaw = base.WorkConfig.EnableBottleJaw;
            cDJ.EnableSolventJaw = base.WorkConfig.EnableSolventJaw;
            mInjectors = new CMultyInjectors(DeviceConfig.InjectorMaxML, StationColNum);
            return true;
        }

        #region 夹爪操作函数

        private int _maxDrugCount = 0;

        //数量大于4，第一批次没有配完，所以全开夹爪
        private long OpenDrugJawForNextLoop()
        {
            long ret = 0;
            //打开放药品
            SetRunState("移动到放药位置");
            ret = MoveToPutDrugPos();
            if (0 == ret) { return 0; }
            //打开夹爪模式1，打开，然后关闭，执行1次,因为要循环下一次了，说明要打开所有西林瓶夹爪
            if (DeviceConfig.TestMode == 0)
            {
                //加工模式
                if (WorkConfig.OpenjawDirect == 1)
                {
                    //需要确认后再打开夹爪，等待启动按钮被按下
                    SetRunState("等待按下启动按钮，确认是否掉落西林瓶");
                    ret = WaitPressDownStartButton();
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }
            SetRunState("打开夹爪");
            cDJ.OpenDrugStationJaw(djClosePosIndex);
            return 1;
        }

        public long OpenDrugAndSolventForNextBatch(int pmaxDrugCount)
        {
            long ret = 0;
            if (pmaxDrugCount > 2)
            {
                //先在放药位置打开3，4排的夹爪，然后移动到放溶媒位置打开1,2行夹爪
                SetRunState("移动到放药位置");
                ret = MoveToPutDrugPos(); if (0 == ret) { return 0; }
            }
            else
            {
                //移动到放溶媒位置
                SetRunState("移动到放溶媒位置！");
                nMotionCtrl.WorkPointID = 7;
                ret = nMotionCtrl.AbsMove(_X, WorkPoint.X_PutSolventPos);
                if (0 == ret)
                {
                    return 0;
                }
                ret = nMotionCtrl.WaitForStop(); if (0 == ret) { return 0; }
            }
            _maxDrugCount = pmaxDrugCount;
            //Thread thread = new Thread(ThreadOpenAndCloseDrugAndSolvent);
            //thread.SetApartmentState(ApartmentState.STA);
            //thread.Start();

            ThreadOpenAndCloseDrugAndSolvent();
            //Task resetJaw = Task.Run(() =>
            //{
            //    ThreadOpenAndCloseDrugAndSolvent();
            //});
            return 1;
        }

        //配药结束，有几个药，打开几个夹爪
        private void ThreadOpenAndCloseDrugAndSolvent()
        {
            SetRunState("在线程中打开关闭夹爪");
            cDJ.OpenAndCloseDrugAndSolvent(_maxDrugCount, djClosePosIndex, DeviceConfig.SolventJawOpenCount);
        }

        public void ResetJaw()
        {
            //tring[] RoatAngle = djParam.DjRunAngle.ToArray();
            SetRunState("复位夹爪");
            cDJ.ResetJaw(djClosePosIndex);
        }

        #endregion 夹爪操作函数

        #region LED 灯操作函数

        private bool GetShowLed(COneLoopStations oneLoop, ref byte[,] SubLED)
        {
            //初始化所有值为1
            for (int i = 0; i < MaxRowPointCount; i++)
            {
                for (int j = 0; j < MaxColPointCount; j++)
                {
                    SubLED[i, j] = 1;
                }
            }

            for (int row = 1; row < StationRowNum; row++)
            {
                for (int col = 0; col < DeviceConfig.StationColNum; col++)
                {
                    if (oneLoop.MultyRowStation[row].RowStations[col].UsedFlag == 1)
                    {
                        SubLED[row - 1, col] = 0;
                    }
                    else
                    {
                        SubLED[row - 1, col] = 1;
                    }
                }
            }
            return true;
        }

        private bool OpenLedForNextLoop(COneLoopStations NextOneLoop)
        {
            //SetRunState("打开下一个循环指示灯");
            if (DeviceConfig.enableMcu == 1)
            {
                byte[,] SubLED = new byte[MaxRowPointCount, MaxColPointCount];
                GetShowLed(NextOneLoop, ref SubLED);
                return cLED.OpenLED(SubLED);
            }
            return true;
        }

        private void GetShowLed(CMS_AdviceAndDrugs adviceAndDrug, ref byte[,] SubLED)
        {
            List<CMS_AdviceAndDrug> allAdvices = adviceAndDrug.adviceAndDrugs;
            //初始化所有值为1
            for (int i = 0; i < MaxRowPointCount; i++)
            {
                for (int j = 0; j < MaxColPointCount; j++)
                {
                    SubLED[i, j] = 1;
                }
            }
            for (int col = 0; col < allAdvices.Count; col++)//医嘱执行单的总个数
            {
                //获取一个医嘱用药的数量
                CMS_AdviceAndDrug ae = allAdvices[col];
                if (ae.AdviceHadStop != 1)
                {
                    //没有停药
                    int count = 0;
                    if (ae.Drugs[0].SOLVENT_FLAG == 2)
                    {
                        count = (int)ae.GetDrugCount() * 2;
                    }
                    else
                    {
                        count = (int)ae.GetDrugCount();
                    }
                    //循环每一行，赋值给当前列
                    for (int row = 0; row < DeviceConfig.StationRowNum; row++)
                    {
                        //初始化的时候，数组内的数据全为1；
                        if (row < count)
                        {
                            SubLED[row, col] = 0;
                        }
                        else
                        {
                            SubLED[row, col] = 1;
                        }
                    }
                }
            }
        }

        public bool OpenLedForFirstLoop(CMS_AdviceAndDrugs adviceAndDrug)
        {
            //SetRunState("显示第一次循环的指示灯");
            if (DeviceConfig.enableMcu == 1)
            {
                byte[,] SubLED = new byte[MaxRowPointCount, MaxColPointCount];
                GetShowLed(adviceAndDrug, ref SubLED);
                return cLED.OpenLED(SubLED);
            }
            return true;
        }

        #endregion LED 灯操作函数

        #region 自动运行

        private int AutoRunCount = 0;
        public int Surpuls_Mode = 0;//结余模式

        //抽出指定mL的溶媒
        private bool FirstPullSolvent = true;

        #region 混配模式

        private int firstUsedColID = 0;
        private int djClosePosIndex = 0;

        public bool AutoRun()
        {
            bool ret = false;
            _isFinished = false;
            HadRinseInjector = false;
            SetRunState("-----------------开始第" + AutoRunCount.ToString() + "次自动配药--------------------");
            startTime = DateTime.Now;
            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
            stopwatch.Start(); //  开始监视代码
            AutoRunCount++;

            try
            {
                firstUsedColID = GetFirstUsedDrugColID();
                Surpuls_Mode = advices.adviceAndDrugs[firstUsedColID].SurPlusMode;
                djClosePosIndex = advices.GetDJClosePosIndex();
                HaveBottleInDevice = true;
                FirstPullSolvent = true;
                if (0 == Surpuls_Mode)
                {
                    //不结余模式
                    SetRunState("不结余模式配药");
                    ret = HP_AutoFlush();
                    HaveBottleInDevice = false;
                }
                else
                {
                    //结余模式
                    SetRunState("结余模式配药");
                    ret = Surplus_AutoRun();
                }
            }
            catch (Exception e)
            {
                SetRunState("自动配药运行出现异常:" + e.Message, LogLevel.Warning);
            }
            finally
            {
                stopwatch.Stop(); //  停止监视
                TimeSpan timeSpan = stopwatch.Elapsed; //  获取总时间
                endTime = DateTime.Now;
                usedTime = Convert.ToInt32(timeSpan.TotalSeconds);
                //Thread thread = new Thread(SaveRecord);
                //thread.Start();
                _isFinished = true;
            }
            SetRunState("----------------自动配药结束-----------------");
            return ret;
        }

        private int GetFirstUsedDrugColID()
        {
            for (int i = 0; i < advices.adviceAndDrugs.Count; i++)
            {
                if (advices.adviceAndDrugs[i].Enable == 1)
                {
                    return i;
                }
            }
            return 0;
        }

        private bool HP_AutoFlush()
        {
            long ret = 0;
            CMultyLoopStations multyLoops = new CMultyLoopStations();
            CMS_AnalyFile anlyFile = new CMS_AnalyFile(advices, WorkPoint, DeviceConfig);
            SetRunState("开始解析，配药医嘱");
            ret = anlyFile.AnalysisFlie(ref multyLoops);
            //配药文件解析正常的情况下，才可以进行配药
            if (ret == 0)
            {
                SetRunState("解析医嘱出现错误", LogLevel.Warning);
                return false;
            }
            int putDrugLoopCount = multyLoops.MultyLoopStation.Count;
            SetRunState("需要放药的次数=" + putDrugLoopCount.ToString());
            for (int putDrugIndex = 0; putDrugIndex < putDrugLoopCount; putDrugIndex++)
            {
                SetRunState("第" + putDrugIndex.ToString() + "循环");
                COneLoopStations oneLoop = multyLoops.MultyLoopStation[putDrugIndex];
                //冲刷配药
                ret = HP_AutoFlushOneLoop(oneLoop);
                if (0 == ret)
                {
                    return false;
                }
                //添加回抽
                ret = RebackPull(oneLoop);
                if (0 == ret)
                {
                    return false;
                }
                //移动去放药位置
                ret = MoveToPutDrugPos();
                if (0 == ret)
                {
                    return false;
                }
                CRJSpeech.SpeakAsync("已经移动到放药位置，可以取走溶媒");
                //判断还需不要再次放药
                if (putDrugIndex + 1 < putDrugLoopCount)
                {
                    SetRunState("需要二次放药！");
                    //获取需要再次放药的信息
                    COneLoopStations NextOneLoop = (COneLoopStations)multyLoops.MultyLoopStation[putDrugIndex + 1].Clone();
                    //打开针剂站
                    SetRunState("只打开西林瓶夹爪");
                    ret = OpenDrugJawForNextLoop();
                    if (0 == ret)
                    {
                        return false;
                    }
                    SetRunState("亮起LED指示灯");
                    OpenLedForNextLoop(NextOneLoop);
                    //MessageBox.Show("是否已经将没有冲配完成的药品放入设备等待冲配?");
                    string str = "是否已经将没有冲配完成的药品放入设备等待冲配?";
                    Application.Current.Dispatcher.Invoke(
                    (Action)delegate ()
                    {
                        _dialogService.ShowDialog("WarningDialog", new DialogParameters($"message={str}"), null);
                    });
                    if (DeviceConfig.enableMcu == 1)
                    {
                        cLED.CloseAllLED();
                    }
                }
            }
            //Y轴移动到零点位置
            SetRunState("Y轴移动到零点位置！");
            ret = YMoveToZeroPos();
            if (0 == ret)
            {
                return false;
            }
            //配药结束
            nMotionCtrl.WriteChannelOut(nMotionCtrl.motionParam.nIOSet.oStartLed, 0);
            if (DeviceConfig.TestMode == 0)
            {
                //加工模式
                if (WorkConfig.OpenjawDirect == 1)
                {
                    //需要确认后再打开夹爪，等待启动按钮被按下
                    SetRunState("需要确认打开夹爪！");
                    ret = WaitPressDownStartButton();
                    if (0 == ret)
                    {
                        return false;
                    }
                }
            }
            SetRunState("打开夹爪");
            ret = OpenDrugAndSolventForNextBatch(multyLoops.MultyLoopStation[putDrugLoopCount - 1].MaxDrugCount);
            if (0 == ret)
            {
                return false;
            }
            SetRunState("夹爪已经打开，可以放药");
            if (WorkConfig.PutSolventFirst == 1)
            {
                Thread.Sleep(2000);
            }
            //移动到放溶媒位置,这个地方需要修改，应该用下一个批次的医嘱？？？？？？？？？？？？？？？？？？？
            SetRunState("移动到放药位置");
            ret = MoveToPutDrugOrSoventPos(multyLoops.MultyLoopStation[0].MaxDrugCount);
            if (0 == ret) { return false; }
            if (WorkMode == 0)
            {
                //单机模式，配完结束后，单机模式，所有的医嘱都是一样的，打开LED
                SetRunState("单机模式：配药结束，亮起LED指示灯");
                OpenLedForNextLoop(multyLoops.MultyLoopStation[0]);
            }
            return true;
        }

        private long HP_AutoFlushOneLoop(COneLoopStations oneLoop)
        {
            long ret = 0;
            bool FlushOKFlag = false;
            //第一步抽取溶媒
            //第一步排出注射器内的液体
            COneRowStation SolventRowStation = oneLoop.MultyRowStation[0];
            SolventRow = SolventRowStation;
            while (!FlushOKFlag)
            {
                ret = HP_PushInAireFromBottleBeforeFlush(oneLoop);
                if (0 == ret)
                {
                    return 0;
                }
                ret = HP_PullOutAireFromBottleBeforeFlush(oneLoop);
                if (0 == ret)
                {
                    return 0;
                }
                ret = HP_RunOneLoop(oneLoop);
                if (0 == ret)
                {
                    if (nMotionCtrl.ExitType == 3)
                    {
                        SetRunState("在配药的过程中，急停按钮被按下，选择了直接退出配药！", LogLevel.Warning);
                        return 0;
                    }
                    else if (nMotionCtrl.ExitType == 2)
                    {
                        //只是选择了退出当前动作，配药还可以从头再来一次

                        ButtonResult mbr = ButtonResult.Yes;
                        Application.Current.Dispatcher.Invoke(
                        (Action)delegate ()
                        {
                            _dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={" 是否要将注射器内的液体打到溶媒袋里面去？"}"), r =>
                            {
                                mbr = r.Result;
                            });
                        });
                        if (mbr == ButtonResult.Yes)
                        {
                            //添加判断，急停按钮是否打开
                            ret = WaitEmgOpen();
                            if (0 == ret)
                            {
                                return 0;
                            }
                            FlushOKFlag = false;
                            //将药液打回溶媒，回复到初始状态
                            SetRunState("回打溶媒并拔针！");
                            int[] validCol = SolventRowStation.GetUsedFlag();
                            ret = Flush_SolventInAndPullInjector(SolventRowStation, validCol, 0);
                            if (0 == ret)
                            {
                                return 0;
                            }
                            ret = nMotionCtrl.WaitForStop();
                            if (0 == ret)
                            { return 0; }
                        }

                        //MessageBoxResult mbr = MessageBox.Show("在配药的过程中出现了异常，是否重新配药？", "操作选择", MessageBoxButton.YesNo);
                        ButtonResult mbr1 = ButtonResult.Yes;
                        Application.Current.Dispatcher.Invoke(
                        (Action)delegate ()
                        {
                            _dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={" 在配药的过程中出现了异常，是否重新配药？"}"), r =>
                            {
                                mbr1 = r.Result;
                            });
                        });
                        if (mbr1 == ButtonResult.Yes)
                        {
                            //选择了重新配药
                        }
                        else
                        {
                            //是按下急停选择了退出
                            SetRunState("急停被按下，选择了退出配药");
                            nMotionCtrl.ExitType = 3;
                            return 0;
                        }
                    }
                    else
                    {
                        SetRunState("急停被按下，选择了退出配药");
                        return 0;
                    }
                }
                else
                {
                    FlushOKFlag = true;
                }
            }
            return 1;
        }

        //释放瓶内原始压强，每个瓶子最多释放5ml空气
        private long HP_PullOutAireFromBottleBeforeFlush(COneLoopStations oneLoop, int StartRow = 1, int loopIndex = 0)
        {
            //瓶内原始压强，添加一个正压放空气的动作,但必须是粉针
            if (oneLoop.UsedDrug.NEEDLE_TYPE == 1)
            {
                //水针
                return 1;
            }
            int[] OrgPress = oneLoop.GetOrgPressure();
            int minOrgPressure = oneLoop.GetMinValue(OrgPress);
            if (minOrgPressure > 0) { return 1; }
            COneRowStation SolventRowStation = oneLoop.MultyRowStation[0];
            long ret = 0;
            int RowStationCount = StationRowNum;
            int increateValue = 1;
            if (oneLoop.UsedDrug.SOLVENT_FLAG == 2)
            {
                //专用溶媒模式
                increateValue = 2;
                StartRow = 2;
            }
            for (int row = StartRow; row < RowStationCount; row += increateValue)
            {
                COneRowStation oneRow = oneLoop.MultyRowStation[row];
                int[] orgPressureValidCol = oneRow.GetOrgPositivePressureFlag();
                //判断该行有没有启用的，就是需要冲入溶液的
                bool usedFlag = oneRow.HaveDrug(orgPressureValidCol);
                if (true == usedFlag)
                {
                    //移动小药所在的行到针管的正上方
                    SetRunState("X轴移动到第" + row.ToString() + "行");
                    ret = XBottleMoveToPuctruePos(oneRow.XPos);
                    if (0 == ret) { return 0; }
                    nMotionCtrl.WorkPointID = row + 1;

                    SetRunState("Y轴移动到抽液高度");
                    ret = Bottle_YMoveToPumpingLow(oneRow, 0);
                    if (0 == ret) { return 0; }

                    SetRunState("注射器抽取空气");
                    ret = HP_PullOutOrgAire(oneRow, orgPressureValidCol);
                    if (0 == ret) { return 0; }
                    ret = Bottle_YPullOutToSafe(oneRow);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
                else
                {
                    break;
                }
            }
            COneRowStation oneRow1 = oneLoop.MultyRowStation[StartRow];
            ret = XieYa_PumpingBackAire(oneRow1);
            if (0 == ret) { return 0; }

            //打回到溶媒袋
            int[] validCol = SolventRowStation.GetUsedFlag();
            ret = Flush_SolventInNoPullOutInjector(SolventRowStation, validCol, loopIndex);
            if (0 == ret) { return 0; }
            ret = nMotionCtrl.WaitForStop();
            if (0 == ret) { return 0; }
            COneRowStation soneRow = oneLoop.MultyRowStation[StartRow];
            if (soneRow.UsedDrug.SOLVENT_FLAG == 2)
            {
                SetRunState("专用溶媒,移动到安全位置");
                ret = YMoveToSafe(); if (0 == ret) { return 0; }
                if (0 == ret)
                {
                    return 0;
                }
            }
            return 1;
        }

        //在冲刷之前注入空气，解决瓶子内负压太大，冲刷不好抽液的问题
        private long HP_PushInAireFromBottleBeforeFlush(COneLoopStations oneLoop, int StartRow = 1, int loopIndex = 0)
        {
            //瓶内原始压强，添加一个正压放空气的动作,但必须是粉针
            //if (oneLoop.UsedDrug.NEEDLE_TYPE == 1)
            //{
            //    //水针
            //    LogMessage("药品类型是水针，不需要注入空气！");
            //    return 1;
            //}
            int[] OrgPress = oneLoop.GetOrgPressure();
            int maxOrgPressure = oneLoop.GetMaxValue(OrgPress);
            if (maxOrgPressure != 2)
            {
                LogMessage("瓶内原始压强不是负压，不用注入空气！ value=" + maxOrgPressure.ToString());
                return 1;
            }//没有负压就直接退出
            COneRowStation SolventRowStation = oneLoop.MultyRowStation[0];
            long ret = 0;
            int RowStationCount = StationRowNum;
            int increateValue = 1;
            if (oneLoop.UsedDrug.SOLVENT_FLAG == 2)
            {
                //专用溶媒模式
                increateValue = 2;
                StartRow = 2;
            }
            for (int row = StartRow; row < RowStationCount; row += increateValue)
            {
                COneRowStation oneRow = oneLoop.MultyRowStation[row];
                int[] orgNegativePressureValidCol = oneRow.GetOrgNegativePressureFlag();
                //判断该行有没有启用的，就是需要冲入溶液的
                bool usedFlag = oneRow.HaveDrug(orgNegativePressureValidCol);
                if (true == usedFlag)
                {
                    //在移动之前判断一下空气的值是否为0
                    //移动小药所在的行到针管的正上方

                    SetRunState("X轴移动到第" + row.ToString() + "行");
                    ret = XBottleMoveToPuctruePos(oneRow.XPos);
                    if (0 == ret) { return 0; }
                    nMotionCtrl.WorkPointID = row + 1;

                    SetRunState("Y轴移动到穿刺起始高度");
                    ret = YMoveToDestPos(WorkPoint.Y_BottleStartPunctureHeight);
                    if (0 == ret) { return 0; }

                    SetRunState("注射器抽取空气");
                    ret = HP_PushInOrgAire(oneRow, orgNegativePressureValidCol);
                    if (0 == ret) { return 0; }
                    ret = Bottle_YPullOutToSafe(oneRow);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
                else
                {
                    LogMessage("不存在原始压强为负压的药品！");
                    break;
                }
            }

            //移动到抽溶媒位置
            if (oneLoop.UsedDrug.NEEDLE_TYPE != 1)
            {
                //不是水针
                nMotionCtrl.WorkPointID = 1;
                ret = XBottleMoveToPuctruePos(WorkPoint.X_StationPos0);
                if (0 == ret) { return 0; }
                COneRowStation soneRow = oneLoop.MultyRowStation[StartRow];
                if (soneRow.UsedDrug.SOLVENT_FLAG == 2)
                {
                    SetRunState("专用溶媒,移动到安全位置");
                    ret = YMoveToSafe(); if (0 == ret) { return 0; }
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }

            return 1;
        }

        #region 泄压回打空气

        private long XieYa_PumpingBackAire(COneRowStation oneRow)
        {
            long ret = 0;
            int[] ViscosityFlag = oneRow.GetViscosityFlag();
            if (AllValueIsZero(ViscosityFlag) == true)
            {
                return 1;
            }
            //在回打溶媒之前，注射器向下拉一下，将针尖内的药粉，吸入注射器内，避免针尖堵针
            double[] hadAire = new double[6];
            SetRunState("执行粘稠向下抽两毫升空气！");
            ret = PullOut2mlAire(ref hadAire, ViscosityFlag);
            if (0 == ret) { return 0; }
            nMotionCtrl.WorkPointID = 1;
            ret = XBottleMoveToPuctruePos(WorkPoint.X_StationPos0);
            if (0 == ret) { return 0; }
            ret = Solvent_YMoveToDstPos(oneRow.UsedSolvent, WorkPoint.Y_SolventHeight);
            if (0 == ret) { return 0; }
            //先回打部分空气
            SetRunState("执行粘稠回打部分空气！");
            ret = InjectorPushOutAire(hadAire, ViscosityFlag);
            if (0 == ret)
            {
                return 0;
            }
            SetRunState("执行粘稠涮洗注射器！");
            ret = InjectorRinse(oneRow, ViscosityFlag, 0);//涮洗注射器
            if (0 == ret)
            {
                return 0;
            }
            return 1;
        }

        private int PullOut2mlAire(ref double[] hadAire, int[] ViscosityFlag)
        {
            int[] hadVolumeFlag = mInjectors.GetHadVolumeFlag();
            int[] validStation = ANDFlag(hadVolumeFlag, ViscosityFlag);
            hadAire = mInjectors.GetInjectHadUsedVolume();
            double[] outAire = ValueToArray(2.0);
            int[] speedPercent = ValueToArray(50);
            long ret = Out_AllZWithSpecifiedPercent(validStation, outAire, speedPercent);
            if (0 == ret)
            {
                return 0;
            }
            mInjectors.SetInjectHadVolume(outAire, validStation);
            return 1;
        }

        private int InjectorPushOutAire(double[] pushOutAire, int[] ViscosityFlag)
        {
            int[] hadVolumeFlag = mInjectors.GetHadVolumeFlag();
            int[] validStation = ANDFlag(hadVolumeFlag, ViscosityFlag);
            int[] speedPercent = ValueToArray(50);
            long ret = In_AllZWithSpecifiedPercent(validStation, pushOutAire, speedPercent);
            if (0 == ret)
            {
                return 0;
            }
            mInjectors.SetInjectHadVolume(pushOutAire, validStation, 0);
            return 1;
        }

        #endregion 泄压回打空气

        //2.抽溶媒的剂量问题
        private long HP_RunOneLoop(COneLoopStations oneLoop)
        {
            SetRunState("开始一次循环配药！");
            long ret = 0;
            if (oneLoop.UsedDrug.SOLVENT_FLAG == 0)
            {
                //普通溶媒
                SetRunState("普通溶媒配药！");
                if (1 == oneLoop.UsedDrug.NEEDLE_TYPE)
                {
                    //水针,一个循环结束之后，必须要打回溶媒袋
                    SetRunState("水针配药");
                    ret = SZ_Operation(oneLoop);
                    if (0 == ret) { return 0; }
                }
                else
                {
                    //粉针
                    SetRunState("粉针配药");
                    ret = HP_FZ_Operation(oneLoop);
                    if (0 == ret) { return 0; }
                }
            }
            else if (oneLoop.UsedDrug.SOLVENT_FLAG == 2)
            {
                SetRunState("专用溶媒配药");
                //专用溶媒
                ret = ZYRM_Operation(oneLoop);
                if (0 == ret) { return 0; }
            }
            else
            {
                //MessageBox.Show("不存在该药的配药模式");
                string str = "不存在该药的配药模式!";
                Application.Current.Dispatcher.Invoke(
                (Action)delegate ()
                {
                    _dialogService.ShowDialog("WarningDialog", new DialogParameters($"message={str}"), null);
                });
                if (DeviceConfig.enableMcu == 1)
                {
                    cLED.CloseAllLED();
                }
            }
            return 1;
        }

        private int HP_PullOutOrgAire(COneRowStation oneRow, int[] validStation)
        {
            double[] outAire = oneRow.GetOrgPullOutAire();
            int[] speedPercent = oneRow.GetOutSolventSpeed();
            //添加判断注射器的容积够不够
            long ret = Out_AllZWithSpecifiedPercent(validStation, outAire, speedPercent);
            if (0 == ret)
            {
                return 0;
            }
            mInjectors.SetInjectHadVolume(outAire, validStation);
            return 1;
        }

        private int HP_PushInOrgAire(COneRowStation oneRow, int[] validStation)
        {
            double[] outAire = oneRow.GetOrgPullOutAire();
            int[] speedPercent = oneRow.GetOutSolventSpeed();
            //添加判断注射器的容积够不够
            long ret = Out_AllZWithSpecifiedPercent(validStation, outAire, speedPercent);
            if (0 == ret)
            {
                return 0;
            }
            //移动到冲刷高度
            SetRunState("Y轴移动到冲刷高度");
            ret = Bottle_YMoveToFlushHight(oneRow);
            if (0 == ret) { return 0; }
            ret = In_AllZWithSpecifiedPercent(validStation, outAire, speedPercent);
            if (0 == ret) { return 0; }

            return 1;
        }

        #endregion 混配模式

        private long MoveToPutDrugOrSoventPos(int maxDrugCount)
        {
            long ret = 0;
            SetRunState("执行放药动作！");
            //Y轴移动到0位
            ret = YMoveToZeroPos();
            if (0 == ret)
            {
                return 0;
            }
            if (maxDrugCount > 2)
            {
                if (WorkConfig.PutSolventFirst == 0)
                {
                    nMotionCtrl.WorkPointID = 6;
                    ret = nMotionCtrl.AbsMove(_X, WorkPoint.X_PutDrugsPos);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
                else
                {
                    //移动到放溶媒位置
                    nMotionCtrl.WorkPointID = 7;
                    ret = nMotionCtrl.AbsMove(_X, WorkPoint.X_PutSolventPos);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }
            else
            {
                //移动到放溶媒位置
                nMotionCtrl.WorkPointID = 7;
                ret = nMotionCtrl.AbsMove(_X, WorkPoint.X_PutSolventPos);
                if (0 == ret)
                {
                    return 0;
                }
            }
            //等待轴运动停止
            ret = nMotionCtrl.WaitForStop(); if (0 == ret) { return 0; }

            return 1;
        }

        public long MoveToPutDrugPos()
        {
            long ret = 0;
            SetRunState("移动到放药位置！");
            //Y轴移动到0位
            ret = ret = YMoveToZeroPos();
            if (0 == ret)
            {
                return 0;
            }
            nMotionCtrl.WorkPointID = 6;
            ret = nMotionCtrl.AbsMove(_X, WorkPoint.X_PutDrugsPos);
            if (0 == ret)
            {
                return 0;
            }
            //等待轴运动停止
            ret = nMotionCtrl.WaitForStop(_X); if (0 == ret) { return 0; }

            return 1;
        }

        //等待按下启动按钮
        private long WaitPressDownStartButton()
        {
            string runState = "配药已经结束，请按下启动按钮，将打开放药夹爪";
            LogMessage(runState);
            if (nMotionCtrl.motionParam.nIOSet.oAlarmLed > 0)
            {
                nMotionCtrl.WriteChannelOut(nMotionCtrl.motionParam.nIOSet.oAlarmLed, 1);
                Thread.Sleep(2000);
                nMotionCtrl.WriteChannelOut(nMotionCtrl.motionParam.nIOSet.oAlarmLed, 0);
            }

            int StartRun = 0;
            nMotionCtrl.ReadChannelInput(nMotionCtrl.motionParam.nIOSet.iStartPort, ref StartRun);
            while (1 != StartRun)
            {
                //等待点击启动按钮
                Thread.Sleep(200);
                nMotionCtrl.ReadChannelInput(nMotionCtrl.motionParam.nIOSet.iStartPort, ref StartRun);
                if (1 == StartRun)
                {
                    nMotionCtrl.WriteChannelOut(nMotionCtrl.motionParam.nIOSet.oStartLed, 1);
                }
                else
                {
                    nMotionCtrl.WriteChannelOut(nMotionCtrl.motionParam.nIOSet.oStartLed, 0);
                }
                int ret1 = 0;
                bool emg = false;
                ret1 = nMotionCtrl.GetEmgState(ref emg);
                if (0 == ret1)
                {
                    break;
                }
                if (emg == false)
                {
                    break;
                }
            }
            return 1;
        }

        #endregion 自动运行

        #region 水针的冲配方式

        //水针冲配
        private long SZ_Operation(COneLoopStations oneLoop, int StartRow = 1, bool PumpBackFlag = false)
        {
            long ret = 0;
            SetRunState("-------水针：开始抽水剂-------");
            mInjectors.InjectorMaxML = DeviceConfig.ShuiZhenMaxML;
            int RowStationCount = StationRowNum;
            COneRowStation SolventRow = oneLoop.MultyRowStation[0];//这个用来确定回打的时候，哪个注射器需要回打
            //有可能一次抽不完，要分多次抽取水针
            for (int row = 1; row < RowStationCount; row++)
            {
                SetRunState("水针：第" + row.ToString() + "行开始抽出水剂！");
                ret = SZ_OneRowPullOut(oneLoop, ref SolventRow, row);
                if (0 == ret)
                {
                    return 0;
                }
            }
            SetRunState("-------水针：抽水剂完成-------");
            return 1;
        }

        private long SZ_OneRowPullOut(COneLoopStations oneLoop, ref COneRowStation SolventRow, int row)
        {
            long ret = 0;
            //获取1行数据
            COneRowStation oneRow = oneLoop.MultyRowStation[row];
            //判断该行有没有启用的，
            bool usedFlag = oneRow.HaveDrug();
            if (true == usedFlag)
            {
                //水针，10ml,20ml,30ml,40ml
                CSZ_Loop sZ_Loop = new CSZ_Loop();
                sZ_Loop = SZ_GetLoopValue(oneRow);
                //解决大于20ml的情况
                //计算需要循环的次数
                int loopCount = sZ_Loop.OneRowLoop.Count();
                SetRunState("第" + row.ToString() + "行,要需要的环次数=" + loopCount.ToString());
                for (int loopIndex = 0; loopIndex < loopCount; loopIndex++)
                {
                    SetRunState("第" + row.ToString() + "行,第" + loopIndex.ToString() + "次循环,抽药液！");
                    CSZ_OneRowStation szOneRow = sZ_Loop.OneRowLoop[loopIndex];
                    //注射器内没有剩余的水针药液，每次都抽满打回
                    SetRunState("X轴移动到第" + row.ToString() + "行位置！");
                    ret = XBottleMoveToPuctruePos(oneRow.XPos);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    //如果是回抽的话先抽空气
                    //Y轴移动到抽取液体高度
                    SetRunState("Y轴移动到抽液高度！");
                    ret = Bottle_YMoveToPumpingLow(oneRow, loopIndex);
                    if (0 == ret) { return 0; }
                    SetRunState("注射器移动到零点位置");
                    //由于注射器打回荣没袋后，有1Ml的回退距离，所以，在启用回抽前，要先将回退的1ML回退到零点位置
                    ret = VentAirFromInjector(szOneRow.UsedFlag, mInjectors.InjectorHadAirVolume);//排除注射器内空气
                    if (0 == ret) { return 0; }
                    //添加回抽等待
                    SetRunState("Z轴向下运动，抽出药液");
                    double[] NeedOutVolume = szOneRow.OneRowOutVolume;
                    int[] FlushOutSpeeds = oneRow.GetFlushOutSpeed(loopIndex);
                    ret = Out_AllZWithSpecifiedPercent(szOneRow.UsedFlag, NeedOutVolume, FlushOutSpeeds);
                    if (0 == ret) { return 0; }
                    mInjectors.SetInjectHadVolume(NeedOutVolume, szOneRow.UsedFlag);
                    //抽液等待
                    SetRunState("抽液等待！");
                    {
                        int maxPumpWait = oneRow.GetMaxPUMPING_WAIT(0);
                        Thread.Sleep(maxPumpWait);
                    }
                    int[] validCol = szOneRow.UsedFlag;
                    //中度负压或重度负压，提前打入空气,但是每个注射器的剩余容积不同
                    //水针，或粉针抽出注入空气体积
                    {
                        //水针，负压，先抽后注入空气
                        SetRunState("水针：注入空气！");
                        int[] inAirFlag = oneRow.GetFlushInAireFlag(validCol, 0);
                        ret = SZ_InAir(oneRow, inAirFlag, 0);
                        if (ret == 0) { return 0; }
                    }
                    //反复抽液,添加判断能不能反复抽拉
                    SetRunState("反复多抽");
                    ret = SZ_RepetitivePushAndPull(oneRow, szOneRow.UsedFlag, loopIndex);
                    if (0 == ret) { return 0; }
                    //移动到安全位置
                    SetRunState("Y轴拔针移动到安全位置");
                    ret = Bottle_YPullOutToSafe(oneRow);
                    if (0 == ret) { return 0; }
                    //抽完溶媒后，判断需不需要回打溶媒
                    bool needFlushToSolvent = szOneRow.WetherNeedBackToSolvent();
                    if (true == needFlushToSolvent)
                    {
                        //需要回打溶媒
                        SetRunState("回打溶媒");
                        int[] solventValidCol = mInjectors.GetHadVolumeFlag();
                        ret = SZ_FlushToSolventAndPullInjector(SolventRow, solventValidCol, loopIndex);
                        if (0 == ret) { return 0; }
                        mInjectors.ResetInjectHadVolume();
                    }
                }

                //这里面添加判断，下一行还有没有药了，如果没有，打回溶媒
                bool nextRowHaveUsedBottle = (oneLoop.MultyRowStation[row + 1]).HaveDrug();
                if (true == nextRowHaveUsedBottle)
                {
                    SetRunState("下一行还有西林瓶需要抽液");
                    bool NeedReback = false;
                    //下一行还有药，判断注射器内的剩余容积，够不够，如果不够，回打溶媒
                    double[] bottleVolume = oneRow.GetBOTTLE_VOLUME();
                    double maxBottleVolume = GetMaxValue(bottleVolume);
                    if (maxBottleVolume <= DeviceConfig.ShuiZhenMaxML)
                    {
                        double[] InjectResidualVolume = mInjectors.GetInjectResidualVolume();
                        for (int i = 0; i < StationColNum; i++)
                        {
                            if (InjectResidualVolume[i] < (double)oneRow.RowStations[i].UsedDrug.BOTTLE_VOLUME)
                            {
                                SetRunState("水剂：注射器容积不够，需要回打！");
                                NeedReback = true;
                                break;
                            }
                        }
                    }
                    if (true == NeedReback)
                    {
                        //注射器的剩余容积，小于西林瓶的容积，则回打溶媒
                        SetRunState("回打到溶媒袋！");
                        int[] solventValidCol = mInjectors.GetHadVolumeFlag();
                        ret = SZ_FlushToSolventAndPullInjector(SolventRow, solventValidCol, 0);
                        if (0 == ret) { return 0; }
                        mInjectors.ResetInjectHadVolume();
                    }
                }
                else
                {
                    //下一行没有药了，回打溶媒
                    //判断注射器内有没有溶媒
                    SetRunState("下一行没有西林瓶需要抽液");
                    bool NeedReback = SZ_JudgeWetherNeedRebackSolvent(oneRow);
                    if (true == NeedReback)
                    {
                        //注射器内有溶媒
                        SetRunState("注射器内有药液，需要回打到溶媒袋！");
                        int[] solventValidCol = mInjectors.GetHadVolumeFlag();
                        ret = SZ_FlushToSolventAndPullInjector(SolventRow, solventValidCol, 0);
                        if (0 == ret) { return 0; }
                        mInjectors.ResetInjectHadVolume();
                    }
                }
            }
            return 1;
        }

        private long SZ_InAir(COneRowStation oneRow, int[] validCol, int loopIndex)
        {
            long ret = 0;
            double[] airml = oneRow.GetFLUSH_AIRE(loopIndex);//要多注入的空气
            int[] inAirSpeed = oneRow.GetFlushInAirSpeed(loopIndex);
            {
                SetRunState("粉剂：回抽注入空气");
                ret = InAir(oneRow, validCol, airml, inAirSpeed);
                if (0 == ret) { return 0; }
            }
            return 1;
        }

        #endregion 水针的冲配方式

        #region 专用溶媒模式

        private long ZYRM_Operation(COneLoopStations oneLoop, int StartRow = 2)
        {
            long ret = 0;
            int RowStationCount = StationRowNum;
            //第一步抽取溶媒
            COneRowStation SolventRowStation = new COneRowStation();
            //普通溶媒
            SolventRowStation = (COneRowStation)oneLoop.MultyRowStation[0].Clone();
            //吸取溶媒
            int LoopIndex = 0;
            SetRunState("---------专用溶媒：开始配药------");
            for (int row = StartRow; row < RowStationCount; row += 2)
            {
                //获取1行数据
                COneRowStation UpRow = oneLoop.MultyRowStation[row - 1];
                COneRowStation CurrentRow = oneLoop.MultyRowStation[row];
                //判断该行有没有启用的，就是需要冲入溶液的
                bool usedFlag = (CurrentRow).HaveDrug();
                if (true == usedFlag)
                {
                    SetRunState("专用溶媒模式：抽溶媒");
                    int[] validCol = UpRow.GetUsedFlag();
                    int[] fzzFlag = CurrentRow.GetFZZFlag();
                    ret = MoveAndExtractSolvent(UpRow, validCol, fzzFlag, LoopIndex);
                    if (0 == ret)
                    {
                        return 0;
                    }

                    SetRunState("专用溶媒模式：冲刷");
                    ret = MoveAndFlush(CurrentRow, validCol, row, LoopIndex, StartRow);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    //抽出液体
                    SetRunState("专用溶媒模式：抽出药液");
                    bool[] isLastBottle = new bool[MaxColPointCount];

                    ret = PullOutVolumeAtLast(CurrentRow, validCol, LoopIndex, isLastBottle);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    //打回到溶媒袋
                    SetRunState("专用溶媒模式：回打溶媒");
                    ret = Flush_SolventInAndPullInjector(SolventRowStation, validCol, LoopIndex);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    ret = nMotionCtrl.WaitForStop();
                    if (0 == ret) { return 0; }
                }
            }
            SetRunState("---------专用溶媒：配药结束------");
            return 1;
        }

        #endregion 专用溶媒模式

        #region 粉针

        private long HP_FZ_Operation(COneLoopStations oneLoop)
        {
            long ret = 0;
            int bottleStartRow = 1;
            mInjectors.InjectorMaxML = DeviceConfig.InjectorMaxML;
            SetRunState("粉针模式：--------开始配药--------");
            int FZZMode = IsFZZ(oneLoop);//只有第一次放药，第一行才会有非整只
            if (1 == FZZMode)
            {
                SetRunState("粉针模式：非整只");
                int[] loopCounts = oneLoop.MultyRowStation[1].GetDispenseMedicineLoopCount();
                int MaxLoopCount = GetMaxValue(loopCounts);
                ret = FZZ_FirstRow(oneLoop, MaxLoopCount);
                if (0 == ret)
                {
                    return 0;
                }
                if ((oneLoop.MaxDrugCount == 1) && (oneLoop.LoopIndex == 0))
                {
                    return 1;
                }
            }
            bottleStartRow = GetFlushStartRow(oneLoop);
            //冲刷配药
            if (oneLoop.UsedDrug.FLUSH_MODE == 0)
            {
                ret = MultyLoopForDrugs(oneLoop, bottleStartRow);
                if (0 == ret) { return 0; }
            }
            else
            {
                SetRunState("没有设置药品的冲配模式！", LogLevel.Warning);
                return 0;
            }
            SetRunState("粉针模式：--------配药结束--------");
            return 1;
        }

        //非整只
        private long FZZ_FirstRow(COneLoopStations oneLoop, int maxDMLoopCount)
        {
            SetRunState("粉针模式-第一行-非整只：配药流程");
            long ret = 0;
            //第一步抽取溶媒
            //第一步排出注射器内的液体
            COneRowStation SolventRowStation = oneLoop.MultyRowStation[0];
            COneRowStation DrugFirstRow = oneLoop.MultyRowStation[1];

            int[] fzzFlag = DrugFirstRow.GetFZZFlag();
            int[] haveDrugFlag = DrugFirstRow.GetUsedFlag();
            //第一行，初始化一些数据
            //第一次先抽出溶媒
            SetRunState("粉针模式-第一行-非整只：抽溶媒");
            ret = N_MoveAndExtractSolvent(WorkPoint.X_StationPos0, DrugFirstRow, haveDrugFlag, fzzFlag, 0);//这一次抽溶媒，第一行所有启用的列都要抽溶媒，不同的是抽溶媒的剂量
            if (0 == ret)
            {
                return 0;
            }
            int[] needLoopCounts = DrugFirstRow.GetDispenseMedicineLoopCount();//获取配药的循环次数
            List<int[]> loopFlags = GetLoopPorpertyEnableFlag(maxDMLoopCount, needLoopCounts);
            for (int dmLoopIndex = 0; dmLoopIndex < maxDMLoopCount; dmLoopIndex++)
            {
                int[] oneLoopFlg = loopFlags[dmLoopIndex];
                {
                    int row = 1;//获取1行数据

                    //判断该行有没有启用的，就是需要冲入溶液的
                    bool usedFlag = (DrugFirstRow).HaveDrug();
                    if (true == usedFlag)
                    {
                        SetRunState("粉针模式-第一行-非整只：冲刷");
                        int[] flushValidCol = GetFlushUsedStation(haveDrugFlag, oneLoopFlg, fzzFlag, dmLoopIndex);
                        if (true == AllValueIsZero(flushValidCol))
                        {
                            continue;
                        }
                        ret = MoveAndFlush(DrugFirstRow, flushValidCol, row, dmLoopIndex);
                        if (0 == ret)
                        {
                            return 0;
                        }
                        //抽出液体
                        SetRunState("粉针模式-第一行-非整只：抽出");
                        bool[] IsLastBottle = new bool[MaxColPointCount];
                        ret = PullOutVolumeAtLast(DrugFirstRow, flushValidCol, dmLoopIndex, IsLastBottle);
                        if (0 == ret)
                        {
                            return 0;
                        }
                        //打回到溶媒袋
                        SetRunState("粉针模式-第一行-非整只：打回溶媒");
                        ret = Flush_SolventInNoPullOutInjector(SolventRowStation, flushValidCol, dmLoopIndex);
                        if (0 == ret)
                        {
                            return 0;
                        }
                        //添加判断，第一行是不是都是非整只的
                        bool AllIsFzz = false;
                        AllIsFzz = AllValueIsZero(fzzFlag);
                        //在轻度难容和重度难容的情况下
                        //不需要继续配，判断需不需要二次循环，目前只支持循环两次
                        if ((dmLoopIndex < (maxDMLoopCount - 1)) && (maxDMLoopCount > 1) && (AllIsFzz == false))
                        {
                            //第一次循环结束后，这是第二次循环,有整只的，需要抽取的溶媒容积
                            SetRunState("粉针模式-第一行-非整只：还需要二次循环配药，抽出溶媒");
                            int[] nextOneLoopFlg = loopFlags[dmLoopIndex + 1];
                            int[] nextSolentValidCol = GetFlushUsedStation(haveDrugFlag, nextOneLoopFlg, fzzFlag, dmLoopIndex + 1);
                            if (false == AllValueIsZero(nextSolentValidCol))
                            {
                                ret = ExtractSolvent(DrugFirstRow, nextSolentValidCol, fzzFlag, dmLoopIndex);
                                if (0 == ret)
                                {
                                    return 0;
                                }
                            }
                            else
                            {
                                //需要二次冲配循环，但是都是非整只，不要二次循环冲刷配药
                            }
                        }
                    }
                }
            }
            //如果都是一支药，则拔出注射器
            {
                //根据药品数量，判断要不要拔针
                int[] validDrugCount = SolventRowStation.GetValidDrugCount();
                int maxValidDrugCount = GetMaxValue(validDrugCount);
                if (maxValidDrugCount == 1)
                {
                    SetRunState("粉针模式-第一行-非整只：只有一只药，回打溶媒后拔针");
                    ret = PullOutFromSolventAfterFlushIn(SolventRowStation, haveDrugFlag);
                    if (0 == ret) { return 0; }
                }
            }
            return 1;
        }

        private int IsFZZ(COneLoopStations oneLooop)
        {
            COneRowStation oneRow = oneLooop.MultyRowStation[1];
            for (int col = 0; col < StationColNum; col++)
            {
                if (1 == oneRow.RowStations[col].FeiZhengZhiMode)
                {
                    return 1;
                }
            }
            return 0;
        }

        //已经配过
        private int[] GetFlushUsedStation(int[] usedFlag, int[] oneLoopFlag, int[] fzzFlag, int loopIndex)
        {
            int[] flags = new int[MaxColPointCount];
            for (int i = 0; i < StationColNum; i++)
            {
                if (0 == loopIndex)
                {
                    flags[i] = usedFlag[i];//配药的第一次循环，整支和非整只都要冲刷
                }
                else
                {
                    //不是第一次冲刷，
                    if (fzzFlag[i] == 1)
                    {
                        //非整只的，不能在二次稀释冲配
                        flags[i] = 0;
                    }
                    else
                    {
                        //整支的
                        if ((usedFlag[i] == 1) && (oneLoopFlag[i] == 1))
                        {
                            //需要多次循环稀释冲配的
                            flags[i] = 1;
                        }
                        else
                        {
                            //只需要一次稀释冲配
                            flags[i] = 0;
                        }
                    }
                }
            }
            return flags;
        }

        private int GetFlushStartRow(COneLoopStations oneLoop)
        {
            //这个函数可能有问题
            int StartRow = 1;
            int FZZMode = IsFZZ(oneLoop);
            if (1 == FZZMode)
            {
                if (oneLoop.LoopIndex == 0)
                {
                    StartRow = 2;
                }
                else
                {
                    StartRow = 1;
                }
            }
            else
            {
                StartRow = 1;
            }
            return StartRow;
        }

        #region 循环配药

        private long MultyLoopForDrugs(COneLoopStations oneLoop, int StartRow = 1)
        {
            //获取最大循环次数
            int maxDMLoopCount = oneLoop.GetMaxDispenseMedicinesLoop();
            LogHelper.Info("最大循环次数=" + maxDMLoopCount);
            //获取第一行数据
            COneRowStation DrugFirstRow = (COneRowStation)oneLoop.MultyRowStation[StartRow].Clone();
            int[] needLoopCounts = DrugFirstRow.GetDispenseMedicineLoopCount();//获取每一站配药的循环次数
            List<int[]> loopFlags = GetLoopPorpertyEnableFlag(maxDMLoopCount, needLoopCounts);
            long ret = 0;
            //冲刷配药循环
            for (int dmLoopIndex = 0; dmLoopIndex < maxDMLoopCount; dmLoopIndex++)
            {
                int[] oneLoopFlg = loopFlags[dmLoopIndex];//获取每一次循环，每个站是否启用
                for (int i = 0; i < StationColNum; i++)
                {
                    string str = "";
                    if (oneLoopFlg[i] == 0)
                    {
                        str = "不启用！";
                    }
                    else
                    {
                        str = "启用！";
                    }
                    LogHelper.Info("配药第一" + dmLoopIndex.ToString() + "循环，站" + i.ToString() + str);
                }
                //第一步抽取溶媒
                int DrugCountOfLoopFlush = oneLoop.GetMinDrugCountOfOneLoop(dmLoopIndex, oneLoopFlg);//获取一次循环配几支药
                COneRowStation SolventRowStation = oneLoop.MultyRowStation[0];
                COneRowStation FirstRowStation = oneLoop.MultyRowStation[StartRow];
                int[] drugValidCol = FirstRowStation.GetUsedFlag();
                int[] fzzFlag = FirstRowStation.GetFZZFlag();
                //吸取溶媒
                int[] validCol = oneLoop.MultyRowStation[StartRow].ANDFlag(oneLoopFlg);// GetFlushUsedStation(drugValidCol, oneLoopFlg, fzzFlag, dmLoopIndex);
                ; if (true == AllValueIsZero(validCol))
                {
                    ret = PullOutFromSolventAfterFlushIn(SolventRowStation, drugValidCol);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    return 1;
                }
                SetRunState("粉针：抽溶媒");
                ret = N_MoveAndExtractSolvent(WorkPoint.X_StationPos0, FirstRowStation, validCol, fzzFlag, dmLoopIndex);
                if (0 == ret)
                {
                    return 0;
                }
                //添加判断是否药旋转瓶子
                if (dmLoopIndex > 0)
                {
                    int enableRoatBottle = FirstRowStation.GetEnableRoateBottleFlag(dmLoopIndex);
                    if (1 == enableRoatBottle)
                    {
                        //移动到放药位置
                        MoveToPutDrugPos();
                        Application.Current.Dispatcher.Invoke(
                        (Action)delegate ()
                        {
                            _dialogService.ShowDialog("SuccessDialog", new DialogParameters($"message={"西林瓶是否已经旋转完成?"}"), null);
                        });
                    }
                }
                switch (DrugCountOfLoopFlush)
                {
                    case 1:
                        {
                            ret = OneLoopOneDrug(oneLoop, oneLoopFlg, StartRow, dmLoopIndex);
                            break;
                        }
                    case 2:
                        {
                            ret = OneLoopTwoDrugs(oneLoop, oneLoopFlg, StartRow, dmLoopIndex);
                            break;
                        }
                    case 4:
                        {
                            ret = OneLoopFourDrugs(oneLoop, oneLoopFlg, StartRow, dmLoopIndex);
                            break;
                        }
                    default:
                        {
                            ret = OneLoopOneDrug(oneLoop, oneLoopFlg, StartRow, dmLoopIndex);
                            break;
                        }
                }
                if (0 == ret)
                {
                    return 0;
                }
                //如果所有的循环都结束了，则拔针
                if (dmLoopIndex == (maxDMLoopCount - 1))
                {
                    ret = PullOutFromSolventAfterFlushIn(SolventRowStation, drugValidCol);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }
            return 1;
        }

        #endregion 循环配药

        #region 冲配方式（抽一次溶媒，配所有的药）

        private long OneLoopFourDrugs(COneLoopStations oneLoop, int[] inValidCol, int StartRow = 1, int LoopIndex = 0)
        {
            long ret = 0;
            int endRow = oneLoop.MaxDrugCount + 1;
            int[] drugValidCol = new int[MaxColPointCount];
            for (int row = StartRow; row < endRow; row++)
            {
                //获取1行数据
                COneRowStation oneRow = oneLoop.MultyRowStation[row];
                drugValidCol = oneRow.ANDFlag(inValidCol);
                //判断该行有没有启用的，就是需要冲入溶液的
                bool usedFlag = oneRow.HaveDrug(drugValidCol);
                if (true == usedFlag)
                {
                    SetRunState("抽一次溶媒配4支药：开始冲刷第" + row.ToString() + "行");
                    ret = MoveAndFlush(oneRow, drugValidCol, row, LoopIndex, StartRow);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    //抽出液体
                    SetRunState("抽一次溶媒配4支药：开始抽出第" + row.ToString() + "行");
                    bool[] isLastBottle = GetIsLastBottleFlag(oneRow, row, 4, endRow);
                    ret = PullOutVolumeAtLast(oneRow, drugValidCol, LoopIndex, isLastBottle);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }
            //打回到溶媒袋
            SetRunState("抽一次溶媒配4支药：回打溶媒");
            COneRowStation SolventRowStation = oneLoop.MultyRowStation[0];
            int[] ValidCol = GetInjectorHaveVolumeFlag(SolventRowStation);
            ret = Flush_SolventInNoPullOutInjector(SolventRowStation, ValidCol, LoopIndex);
            if (0 == ret)
            {
                return 0;
            }
            ret = nMotionCtrl.WaitForStop();
            if (0 == ret) { return 0; }
            SetRunState("抽一次溶媒配4支药：-------配药结束---------");

            return 1;
        }

        private bool[] GetIsLastBottleFlag(COneRowStation oneRow, int row, int drugCountOfLoop, int endRow)
        {
            int[] drugValidCol = oneRow.GetUsedFlag();
            bool[] isLastBottle = new bool[MaxColPointCount];
            for (int i = 0; i < StationColNum; i++)
            {
                if (4 == drugCountOfLoop)
                {
                    //一次溶媒配四支药
                    if (drugValidCol[i] == 1)
                    {
                        if (row == oneRow.RowStations[i].ValidDrugCount)
                        {
                            isLastBottle[i] = true;
                        }
                        else
                        {
                            isLastBottle[i] = false;
                        }
                    }
                    else
                    {
                        isLastBottle[i] = false;
                    }
                }
                else
                {
                    //一次溶媒配两支药
                    if (drugValidCol[i] == 1)
                    {
                        if ((row == oneRow.RowStations[i].ValidDrugCount) || (row == (endRow - 1)))
                        {
                            isLastBottle[i] = true;
                        }
                        else
                        {
                            isLastBottle[i] = false;
                        }
                    }
                    else
                    {
                        isLastBottle[i] = false;
                    }
                }
            }
            return isLastBottle;
        }

        private int[] GetInjectorHaveVolumeFlag(COneRowStation oneRow)
        {
            double[] backDistance = oneRow.GetInjcetBackDistance();
            int[] validCol = new int[MaxColPointCount];
            for (int i = 0; i < StationColNum; i++)
            {
                if (mInjectors.injectors[i].InjectHadVolume > backDistance[i])
                {
                    validCol[i] = 1;
                }
                else
                {
                    validCol[i] = 0;
                }
            }
            return validCol;
        }

        #endregion 冲配方式（抽一次溶媒，配所有的药）

        #region 冲配方式（抽一次溶媒，打两只药）

        private long OneLoopTwoDrugs(COneLoopStations oneLoop, int[] inValidCol, int StartRow = 1, int loopIndex = 0)
        {
            SetRunState("抽一次溶媒配2支药：-------开始配药---------");
            long ret = 0;
            int RowStationCount = StationRowNum;
            int startRow = StartRow;
            int endRow = StartRow + 2;
            bool FirstOverFlag = false;
            bool OKFlag = false;
            while (!OKFlag)
            {
                for (int row = startRow; row < endRow; row++)
                {
                    //获取1行数据
                    COneRowStation oneRowDrug = oneLoop.MultyRowStation[row];
                    //将注射器内的容积，赋值给当前行
                    int[] validCol = oneRowDrug.ANDFlag(inValidCol);
                    bool usedFlag = oneRowDrug.HaveDrug(inValidCol);
                    if (true == usedFlag)
                    {
                        SetRunState("抽一次溶媒配2支药：冲刷第" + row.ToString() + "行");
                        ret = MoveAndFlush(oneRowDrug, validCol, row, loopIndex, startRow);
                        if (0 == ret)
                        {
                            return 0;
                        }
                        //抽出液体
                        SetRunState("抽一次溶媒配2支药：抽出第" + row.ToString() + "行");
                        bool[] isLastBottle = GetIsLastBottleFlag(oneRowDrug, row, 2, endRow);
                        ret = PullOutVolumeAtLast(oneRowDrug, validCol, loopIndex, isLastBottle);
                        //将更改后的注射器容积，赋值给溶媒行
                        if (0 == ret)
                        {
                            return 0;
                        }
                    }
                }
                if (FirstOverFlag == false)
                {
                    if (oneLoop.MaxDrugCount > StartRow + 1)
                    {
                        //药品数量大于2只
                        //打回到溶媒袋,但不拔针
                        SetRunState("抽一次溶媒配2支药：药品数量大于2，回打溶媒不拔针");
                        int[] validCol = GetInjectorHaveVolumeFlag(SolventRow);
                        ret = Flush_SolventInNoPullOutInjector(SolventRow, validCol, loopIndex);
                        if (0 == ret)
                        {
                            return 0;
                        }
                        startRow = endRow;
                        endRow = RowStationCount;
                        FirstOverFlag = true;
                        COneRowStation nextOneRowDrug = oneLoop.MultyRowStation[startRow];
                        validCol = nextOneRowDrug.ANDFlag(inValidCol);
                        int[] fzzFlag = nextOneRowDrug.GetFZZFlag();
                        ret = ExtractSolvent(nextOneRowDrug, validCol, fzzFlag, loopIndex);
                        if (0 == ret)
                        {
                            return 0;
                        }
                    }
                    else
                    {
                        //药品数量<=2
                        //打回到溶媒袋
                        SetRunState("抽一次溶媒配2支药：药品数量小于等于2，回打溶媒并拔针");
                        int[] validCol = GetInjectorHaveVolumeFlag(SolventRow);
                        ret = Flush_SolventInNoPullOutInjector(SolventRow, validCol, loopIndex);
                        if (0 == ret)
                        {
                            return 0;
                        }
                        OKFlag = true;
                    }
                }
                else
                {
                    //打回到溶媒袋
                    SetRunState("抽一次溶媒配2支药：药品数量大于2，回打溶媒");
                    int[] validCol = GetInjectorHaveVolumeFlag(SolventRow);
                    ret = Flush_SolventInNoPullOutInjector(SolventRow, validCol, loopIndex);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    OKFlag = true;
                }
                ret = nMotionCtrl.WaitForStop();
                if (0 == ret) { return 0; }
                //移动去放药位置
                nMotionCtrl.WorkPointID = 6;
            }
            SetRunState("抽一次溶媒配2支药：-------配药结束---------");
            return 1;
        }

        #endregion 冲配方式（抽一次溶媒，打两只药）

        #region 轻度难容和重度难容的配药方式

        private long OneLoopOneDrug(COneLoopStations oneLoop, int[] inValidCol, int StartRow = 1, int dmLoopIndex = 0)
        {
            long ret = 0;
            int RowStationCount = StationRowNum;
            for (int row = StartRow; row < RowStationCount; row++)
            {
                bool NextRowHaveBottle = false;//是否继续抽溶媒标志位                                                //获取1行数据
                COneRowStation drugRow = oneLoop.MultyRowStation[row];
                //判断该行有没有启用的，就是需要冲入溶液的
                bool usedFlag = drugRow.HaveDrug(inValidCol);
                if (true == usedFlag)
                {
                    //移动小药所在的行到针管的正上方
                    nMotionCtrl.WorkPointID = row + 1;
                    //进行药品溶解动作
                    SetRunState("抽一次溶媒配1支药：冲刷第" + row.ToString() + "行");
                    int[] validCol = drugRow.ANDFlag(inValidCol);
                    ret = MoveAndFlush(drugRow, validCol, row, dmLoopIndex);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    //抽出液体
                    SetRunState("抽一次溶媒配1支药：抽出第" + row.ToString() + "行");
                    bool[] isLastBottle = new bool[MaxColPointCount];

                    ret = PullOutVolumeAtLast(drugRow, validCol, dmLoopIndex, isLastBottle);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    //打回到溶媒袋
                    SetRunState("抽一次溶媒配1支药：第" + row.ToString() + "行回打溶媒");
                    ret = Flush_SolventInNoPullOutInjector(SolventRow, validCol, dmLoopIndex);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    COneRowStation NextRow = new COneRowStation();
                    //在打回到溶媒袋之后，在判断下一行有没有要冲配的药
                    if (row + 1 < RowStationCount)
                    {
                        NextRow = (COneRowStation)oneLoop.MultyRowStation[row + 1].Clone();
                        bool usedFlag1 = NextRow.HaveDrug(inValidCol);
                        if (true == usedFlag1)
                        {
                            //下一排有西林瓶需要冲配
                            NextRowHaveBottle = true;
                            //SetUsedSolvent(ref SolventRowStation, NextRow);
                        }
                        else
                        {
                            //没有西林瓶需要冲配
                            NextRowHaveBottle = false;
                        }
                    }
                    else
                    {
                        NextRowHaveBottle = false;
                    }
                    //if (false == NextRowHaveBottle)
                    //{
                    //    //如果最后一行没有要配的西林瓶，将地一样的配药标志位赋值给溶媒
                    //    //SetUsedSolvent(ref SolventRowStation, oneLoop.MultyRowStation[StartRow]);
                    //}
                    //判断下面还有没有要冲配的西林瓶，如果有，则针不拔出，继续抽溶媒，如果没有，Y轴移动到安全位置
                    if (true == NextRowHaveBottle)
                    {
                        //这是第一次循环的时候要抽取的溶媒。,抽溶媒,然后Y轴移动安全位置?????
                        SetRunState("抽一次溶媒配1支药：抽溶媒");
                        validCol = NextRow.ANDFlag(inValidCol);
                        int[] fzzFlag = NextRow.GetFZZFlag();
                        ret = ExtractSolvent(NextRow, validCol, fzzFlag, dmLoopIndex);
                        if (0 == ret)
                        {
                            return 0;
                        }
                    }
                }
            }
            return 1;
        }

        #endregion 轻度难容和重度难容的配药方式

        #endregion 粉针

        #region 溶媒操作函数

        private long MoveAndExtractSolvent(COneRowStation oneRow, int[] usedColFlag, int[] fzzFlag, int dmLoopIndex)
        {
            long ret = 0;
            SetRunState("开始执行抽溶媒动作");
            //判断所有的列是否要抽取溶媒
            bool HaveSolvent = oneRow.HaveDrug(usedColFlag);
            if (true == HaveSolvent)
            {
                nMotionCtrl.WorkPointID = oneRow.RowID;
                //需要抽取溶媒，移动X轴到抽取溶媒位置
                ret = XSolventMoveToExtractPos(oneRow.XPos);
                if (0 == ret) { return 0; }
                bool extractSolventOkFlag = false;
                while (!extractSolventOkFlag)
                {
                    ret = ExtractSolvent(oneRow, usedColFlag, fzzFlag, dmLoopIndex);
                    if ((0 == ret))
                    {
                        if ((nMotionCtrl.ExitType == 2))
                        {
                            //选择则了退出当前动作，并且Y轴移动到了0点位值
                            //Y轴移动到安全位置
                            //MessageBoxResult mbr = MessageBox.Show("抽取溶媒的过程中出现异常，是否重新抽取溶媒,如果重新抽取溶媒，请打开急停按钮", "操作选择", MessageBoxButton.YesNo);
                            ButtonResult mbr = ButtonResult.Yes;//
                            Application.Current.Dispatcher.Invoke(
                            (Action)delegate ()
                            {
                                _dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={"抽取溶媒的过程中出现异常，是否重新抽取溶媒,如果重新抽取溶媒，请打开急停按钮"}"), r =>
                                {
                                    mbr = r.Result;
                                });
                            });
                            if (mbr == ButtonResult.Yes)
                            {
                                extractSolventOkFlag = false;
                                nMotionCtrl.ExitType = 0;
                                //判断急停按钮是否打开
                                ret = ret = WaitEmgOpen();
                                if (0 == ret)
                                {
                                    return 0;
                                }
                            }
                            else
                            {
                                //选择了不继续抽溶媒，而是直接退出
                                nMotionCtrl.ExitType = 3;
                                return 0;
                            }
                        }
                        else
                        {
                            //选择的是直接退出配药动作
                            return 0;
                        }
                    }
                    else
                    {
                        //
                        nMotionCtrl.ExitType = 0;
                        extractSolventOkFlag = true;
                    }
                }
            }
            return 1;
        }

        private long ExtractSolvent(COneRowStation oneRow, int[] usedColFlag, int[] fzzFlag, int loopIndex)
        {
            long ret = 0;
            //移动Y轴到要抽溶媒的高度
            if (oneRow.UsedDrug.SOLVENT_FLAG == 2)
            {
                //专用溶媒，在放西林瓶位置，抽液在最低位,专用溶媒只循环一次
                ret = Bottle_YMoveToPumpingLow(oneRow, loopIndex);
            }
            else
            {
                //普通溶媒，row=0;
                ret = Solvent_YMoveToDstPos(oneRow.UsedSolvent, WorkPoint.Y_SolventHeight);
            }
            if (0 == ret) { return 0; }
            ret = Abs_AllUsedZMoveToZero(usedColFlag);
            if (0 == ret)
            {
                return 0;
            }
            //抽出启用站的溶媒
            ret = ExtractUsedSolvent(oneRow, usedColFlag, fzzFlag, loopIndex);
            if (0 == ret)
            {
                return 0;
            }
            Thread.Sleep(1000);
            ret = Solvent_PullOutInject(oneRow, usedColFlag);//Solvent_YMoveToDstPos(oneRow.UsedSolvent, WorkPoint.Y_SafeHeight);
            if (0 == ret) { return 0; }
            return 1;
        }

        private bool HadRinseInjector = false;

        private long ExtractUsedSolvent(COneRowStation oneRow, int[] usedColFlag, int[] fzzFlag, int loopIndex)
        {
            long ret = 0;
            if (FirstPullSolvent == true)
            {
                ret = InjectorRinse(oneRow, usedColFlag, loopIndex);//涮洗注射器
                if (0 == ret)
                {
                    return 0;
                }
                FirstPullSolvent = false;
            }
            //非整只模式
            double[] OutMl = oneRow.GetFlushOutSolventVolume(fzzFlag, usedColFlag, loopIndex);
            //这个地方，抽专用溶媒可能抽不干净，
            if (oneRow.UsedDrug.SOLVENT_FLAG != 2)
            {
                //不是专用溶媒
                int[] outSolventSpeed = oneRow.GetOutSolventSpeed();
                ret = Out_AllZWithSpecifiedPercent(usedColFlag, OutMl, outSolventSpeed);
                if (0 == ret)
                {
                    return 0;
                }
                HadRinseInjector = false;
            }
            else
            {
                //专用溶媒使用的是冲刷抽出慢速度，这个地方可能抽不干净，也需要添加反复多抽，或多抽体积？？？？？？？？？？？？？？
                int[] flushOutSlowSpeed = oneRow.GetFlushOutSlowSpeed(loopIndex);
                int[] usedFlag = oneRow.GetUsedFlag();
                ret = Out_AllZWithSpecifiedPercent(usedColFlag, OutMl, flushOutSlowSpeed);
                if (0 == ret)
                {
                    return 0;
                }
                HadRinseInjector = false;
            }

            mInjectors.SetInjectHadVolume(OutMl, usedColFlag);
            return 1;
        }

        private long N_MoveAndExtractSolvent(double solventPos, COneRowStation oneRow, int[] usedColFlag, int[] fzzFlag, int dmLoopIndex)
        {
            long ret = 0;
            SetRunState("开始执行抽溶媒动作");
            //判断所有的列是否要抽取溶媒
            bool HaveSolvent = oneRow.HaveDrug(usedColFlag);
            if (true == HaveSolvent)
            {
                nMotionCtrl.WorkPointID = oneRow.RowID;
                //需要抽取溶媒，移动X轴到抽取溶媒位置
                ret = XSolventMoveToExtractPos(solventPos);
                if (0 == ret) { return 0; }
                bool extractSolventOkFlag = false;
                while (!extractSolventOkFlag)
                {
                    ret = ExtractSolvent(oneRow, usedColFlag, fzzFlag, dmLoopIndex);
                    if ((0 == ret))
                    {
                        if ((nMotionCtrl.ExitType == 2))
                        {
                            //选择则了退出当前动作，并且Y轴移动到了0点位值
                            //Y轴移动到安全位置
                            //MessageBoxResult mbr = MessageBox.Show("抽取溶媒的过程中出现异常，是否重新抽取溶媒,如果重新抽取溶媒，请打开急停按钮", "操作选择", MessageBoxButton.YesNo);

                            ButtonResult mbr = ButtonResult.Yes;//
                            Application.Current.Dispatcher.Invoke(
                            (Action)delegate ()
                            {
                                _dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={"抽取溶媒的过程中出现异常，是否重新抽取溶媒,如果重新抽取溶媒，请打开急停按钮"}"), r =>
                                {
                                    mbr = r.Result;
                                });
                            });
                            if (mbr == ButtonResult.Yes)
                            {
                                extractSolventOkFlag = false;
                                nMotionCtrl.ExitType = 0;
                                //判断急停按钮是否打开
                                ret = ret = WaitEmgOpen();
                                if (0 == ret)
                                {
                                    return 0;
                                }
                            }
                            else
                            {
                                //选择了不继续抽溶媒，而是直接退出
                                nMotionCtrl.ExitType = 3;
                                return 0;
                            }
                        }
                        else
                        {
                            //选择的是直接退出配药动作
                            return 0;
                        }
                    }
                    else
                    {
                        //
                        nMotionCtrl.ExitType = 0;
                        extractSolventOkFlag = true;
                    }
                }
            }
            return 1;
        }

        //涮洗注射器动作
        private long InjectorRinse(COneRowStation oneRow, int[] usedColFlag, int loopIndex)
        {
            long ret = 0;
            if (true == AllValueIsZero(usedColFlag))
            {
                return 1;
            }
            if (false == HadRinseInjector)
            {
                int[] count = oneRow.GetFlushInjectorRinseCount(loopIndex);
                double[] volumes = oneRow.GetInjectorRinseVolume(loopIndex);
                int[] percents = oneRow.GetOutSolventSpeed();
                int maxCount = GetMaxValue(count);
                for (int i = 0; i < maxCount; i++)
                {
                    //如果刷洗注射器的次数不一样，则按最大刷洗次数执行
                    ret = Out_AllZWithSpecifiedPercent(usedColFlag, volumes, percents);
                    if (0 == ret)
                    {
                        return 0;
                    }
                    ret = Abs_AllUsedZMoveToZero(usedColFlag);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
                mInjectors.ResetInjector(usedColFlag);
                HadRinseInjector = true;
                return 1;
            }

            return 1;
        }

        //注入溶媒袋
        private long SZ_FlushToSolventAndPullInjector(COneRowStation oneRow, int[] validCol, int loopIndex)
        {
            long ret = 0;
            bool PumpBack = false;
            ret = SolventBag_InAndPullInjector(oneRow, validCol, PumpBack, loopIndex);
            if (0 == ret) { return 0; }
            return 1;
        }

        public long Flush_SolventInAndPullInjector(COneRowStation oneRow, int[] validCol, int loopIndex)
        {
            long ret = 0;
            bool PumpBack = false;
            ret = SolventBag_InAndPullInjector(oneRow, validCol, PumpBack, loopIndex);
            if (0 == ret) { return 0; }
            return 1;
        }

        private long Flush_SolventInNoPullOutInjector(COneRowStation oneRow, int[] validCol, int loopIndex)
        {
            bool PumpBack = false;
            return SolventBag_InNoPullOutInjector(oneRow, validCol, PumpBack, loopIndex);
        }

        public long PumpBack_SolventInAndPullInjector(COneRowStation oneRow, int[] validCol, int loopIndex)
        {
            long ret = 0;
            bool PumpBack = true;
            ret = SolventBag_InAndPullInjector(oneRow, validCol, PumpBack, loopIndex);
            if (0 == ret) { return 0; }
            return 1;
        }

        //private long PumpBack_SolventInNoPullOutInjector(COneRowStation oneRow, int[] validCol, int loopIndex)
        //{
        //    bool PumpBack = true;
        //    return SolventBag_InNoPullOutInjector(oneRow, validCol, PumpBack, loopIndex);
        //}
        private long SolventBag_InAndPullInjector(COneRowStation oneRow, int[] validCol, bool PumpBack, int loopIndex)
        {
            SetRunState("开始打回溶媒并拔针动作");
            bool[] needHome = new bool[MaxColPointCount];
            long ret = 0;
            //将注射器内的药液全部打入溶媒袋内
            ret = SolventBag_InNoPullOutInjector(oneRow, validCol, PumpBack, loopIndex);
            if (0 == ret)
            {
                return 0;
            }
            ret = PullOutFromSolventAfterFlushIn(oneRow, validCol);
            if (0 == ret)
            {
                return 0;
            }
            mInjectors.ResetInjectHadVolume();
            return 1;
        }

        private long SolventBag_InNoPullOutInjector(COneRowStation oneRow, int[] validCol, bool PumpBack, int loopIndex)
        {
            long ret = 0;
            SetRunState("回打溶媒并拔针");
            bool HaveSolventFlag = oneRow.HaveDrug();
            if (true == HaveSolventFlag)
            {
                //移动X轴到抽溶媒位置
                ret = SolventBag_FlushInOk(oneRow, validCol, PumpBack, loopIndex);
                if (0 == ret)
                {
                    return 0;
                }
                ret = SolventBag_WetherAtLimitPos(oneRow, validCol);
                if (0 == ret)
                {
                    return 0;
                }
                //这个时候注射器的针尖还是在溶媒袋内的
                ret = InjectorRinse(oneRow, validCol, loopIndex);
                if (0 == ret)
                {
                    return 0;
                }
            }
            mInjectors.ResetInjector(validCol);
            return 1;
        }

        private long SolventBag_FlushInOk(COneRowStation oneRow, int[] validCol, bool PumpBack, int loopIndex)
        {
            long ret = 0;
            bool OKFlag = false;
            while (!OKFlag)
            {
                ret = SolventBag_FlushIn(oneRow, validCol, PumpBack, loopIndex);
                if (1 == ret)
                {
                    OKFlag = true;
                    return 1;
                }
                else
                {
                    if (2 == nMotionCtrl.ExitType)
                    {
                        //退出当前动作
                        //MessageBoxResult mbr = MessageBox.Show("回打溶媒的过程中出现异常，是否重新回打溶媒,如果回打取溶媒，请打开急停按钮，选择《是》", "操作选择", MessageBoxButton.YesNo);

                        ButtonResult mbr = ButtonResult.Yes;//
                        Application.Current.Dispatcher.Invoke(
                        (Action)delegate ()
                        {
                            _dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={"回打溶媒的过程中出现异常，是否重新回打溶媒,如果回打取溶媒，请打开急停按钮"}"), r =>
                            {
                                mbr = r.Result;
                            });
                        });
                        if (mbr == ButtonResult.Yes)
                        {
                            OKFlag = false;
                            nMotionCtrl.ExitType = 0;
                            //判断急停按钮是否打开
                            ret = ret = WaitEmgOpen();
                            if (0 == ret)
                            {
                                return 0;
                            }
                        }
                        else
                        {
                            //选择了不继续抽溶媒，而是直接退出
                            nMotionCtrl.ExitType = 3;
                            return 0;
                        }
                    }
                    else
                    {
                        //选择的是直接退出配药动作
                        return 0;
                    }
                }
            }
            return 1;
        }

        private long SolventBag_FlushIn(COneRowStation oneRow, int[] validCol, bool PumpBack, int loopIndex)
        {
            long ret = 0;
            nMotionCtrl.WorkPointID = 1;
            ret = XSolventMoveToExtractPos(WorkPoint.X_StationPos0);
            if (0 == ret) { return 0; }
            ret = Solvent_YMoveToDstPos(oneRow.UsedSolvent, WorkPoint.Y_SolventHeight);
            if (0 == ret) { return 0; }
            int[] speedPercents = new int[MaxColPointCount];
            if (PumpBack == true)
            {
                //回抽回打
                speedPercents = oneRow.GetFlushPumpBackSolventPushBackSpeed(loopIndex);
            }
            else
            {
                //冲刷后回打溶媒
                speedPercents = oneRow.GetFlushSolventPushBackSpeed(loopIndex);
            }
            ret = Solvent_AllZMoveToZero(oneRow, validCol, speedPercents);
            if (0 == ret)
            {
                return 0;
            }
            mInjectors.ResetInjector(validCol);
            return 1;
        }

        private long SolventBag_WetherAtLimitPos(COneRowStation oneRow, int[] validCol)
        {
            long ret = 0;
            bool[] needHome = new bool[MaxColPointCount];
            //移动ZUV到上限为并停止,目的是为了将针管内的液体全部排除
            for (short i = 0; i < StationColNum; i++)
            {
                if ((oneRow.RowStations[i].UsedFlag == 1) && (validCol[i] == 1))
                {
                    //读取IO信号的状态，
                    bool LimitState = false;
                    int AxisID = _Z + i;
                    if (nMotionCtrl.AxisEnable[AxisID] == false)
                    {
                        needHome[i] = false;
                        continue;
                    }
                    nMotionCtrl.GetLimitState(AxisID, LmtType.Nlmt, ref LimitState);
                    if (false == LimitState)
                    {
                        //没有感应到传感器，需要移动到限位在停止
                        for (short j = 0; j < 80; j++)
                        {
                            ret = nMotionCtrl.RelMove(AxisID, -1);
                            if (0 == ret)
                            {
                                return 0;
                            }
                            ret = nMotionCtrl.WaitForStop(); if (0 == ret) { return 0; }
                            nMotionCtrl.GetLimitState(AxisID, LmtType.Nlmt, ref LimitState);
                            if (true == LimitState)
                            {
                                break;
                            }
                        }

                        needHome[i] = true;
                    }
                    else
                    {
                        needHome[i] = false;
                    }
                }
            }
            //ret = nMotionCtrl.WaitForStop();
            //if (0 == ret) { return 0; }
            //ZUV,离开限为，并将当前位置清零
            for (short i = 0; i < StationColNum; i++)
            {
                if (oneRow.RowStations[i].UsedFlag == 1)
                {
                    if (true == needHome[i])
                    {
                        //只要又一个需要回零，则全部回零，开启线程回零
                        ret = nMotionCtrl.StartHome(_Z + i);
                        if (0 == ret)
                        {
                            return 0;
                        }
                    }
                }
            }
            return 1;
        }

        private long PullOutFromSolventAfterFlushIn(COneRowStation oneRow, int[] validCol)
        {
            long ret = 0;
            bool HaveSolventFlag = (oneRow).HaveDrug();
            if (HaveSolventFlag == true)
            {
                ret = Solvent_PullOutInject(oneRow, validCol);
                if (0 == ret) { return 0; }
            }
            return 1;
        }

        private long Solvent_PullOutInject(COneRowStation oneRow, int[] inValidCol)
        {
            long ret = 0;
            int[] injectorBackFlag = new int[MaxColPointCount];
            if (oneRow.UsedDrug.SOLVENT_FLAG == 0)
            {
                //普通溶媒拔针，添加注射器回退动作
                //Y轴移动到穿刺起始高度，
                ret = Solvent_YMoveToDstPos(oneRow.UsedSolvent, WorkPoint.Y_SolventStartPunctureHeight);
                if (0 == ret) { return 0; }
                //注射器回抽，解决注射器，针尖内液体冒出
                double[] daml = oneRow.GetInjcetBackDistance();
                //获取注射器回退标志位
                for (int col = 0; col < StationColNum; col++)
                {
                    if (mInjectors.InjectorHadAirVolume[col] < daml[col])
                    {
                        //说明注射器没有回退
                        injectorBackFlag[col] = 1;
                    }
                    else
                    {
                        injectorBackFlag[col] = 0;
                    }
                }
                ret = Out_ALLZWithWorkSpeed(injectorBackFlag, daml);
                if (0 == ret)
                {
                    return 0;
                }
                mInjectors.SetInjectorHadAirVolume(daml, injectorBackFlag);
            }
            ret = Solvent_PlugOutSafe(oneRow.UsedDrug);
            if (0 == ret) { return 0; }
            return 1;
        }

        #endregion 溶媒操作函数

        #region 结余模式

        //public bool EnableOneBottleForMultySolvent = true;

        #region 剂量相同的结余模式

        public void ResetRemainDrugDose()
        {
            RemainDrugDose = new float[MaxColPointCount];
        }

        private bool Surplus_AutoRun()
        {
            long ret = 0;
            try
            {
                ret = Surplus_RunOneLoop();
            }
            catch (Exception e)
            {
                SetRunState("自动配药运行出现异常:" + e.Message, LogLevel.Warning);
            }
            finally
            {
                //IsFinished = true;
            }
            if (0 == ret)
            {
                return false;
            }
            return true;
        }

        private long Surplus_RunOneLoop()
        {
            long ret = 0;
            try
            {
                ret = Surplus_RealDoseLessThanDose();//结余相同剂量模式
                if (0 == ret) { return 0; }
                //配药结束
                nMotionCtrl.WriteChannelOut(nMotionCtrl.motionParam.nIOSet.oStartLed, 0);
                if (DeviceConfig.TestMode == 0)
                {
                    //加工模式
                    if (WorkConfig.OpenjawDirect == 1)
                    {
                        //需要确认后再打开夹爪，等待启动按钮被按下
                        ret = WaitPressDownStartButton();
                        if (0 == ret)
                        {
                            return 0;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                SetRunState("自动配药运行出现异常:" + e.Message, LogLevel.Warning);
            }
            finally
            {
                //IsFinished = true;
            }
            return 1;
        }

        private int Surplus_RealDoseLessThanDose()
        {
            long ret = 0;
            int loopIndex = 0;
            //实际使用剂量小于，单个西林瓶的剂量
            //解析文件
            Surplus_COneLoopStations Surplus_OneLoop = new Surplus_COneLoopStations();
            CMS_AnalyFile anlyFile = new CMS_AnalyFile(advices, WorkPoint, DeviceConfig);
            SetRunState("开始解析，配药医嘱");
            ret = anlyFile.Surplus_AnalysisFlie(ref Surplus_OneLoop);
            //配药文件解析正常的情况下，才可以进行配药
            if (ret == 0)
            {
                SetRunState("解析医嘱出现错误", LogLevel.Warning);
                return 0;
            }
            ret = YMoveToZeroPos();
            if (0 == ret)
            {
                return 0;
            }

            #region 抽溶媒和冲刷

            COneRowStation SolventRowStation = Surplus_OneLoop.OneLoopStation.MultyRowStation[0];
            COneRowStation oneRow = Surplus_OneLoop.OneLoopStation.MultyRowStation[1];
            bool firstSolvent = false;
            //判断是不是要抽取溶媒
            long NeedPullSolvent = WetherNeedPullOutSolvent();
            if (1 == NeedPullSolvent)
            {
                //需要抽取溶媒
                RemainDrugDose = Surplus_OneLoop.DrugDose;
                //1.移动到溶媒位置抽取溶媒
                ret = Surplus_MoveAndExtractSolvent(SolventRowStation);
                if (0 == ret)
                {
                    return 0;
                }
                //判断该行有没有启用的，就是需要冲入溶液的
                bool usedFlag = (oneRow).HaveDrug();
                if (true == usedFlag)
                {
                    //移动小药所在的行到针管的正上方
                    //进行药品溶解动作
                    ret = Surplus_MoveAndFlush(oneRow);
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
                firstSolvent = true;
            }

            #endregion 抽溶媒和冲刷

            if (false == firstSolvent)
            {
                //不是第一批次溶媒，不需要移动到抽药位置，直接进行抽液
                //移动到抽药液位置，
                ret = nMotionCtrl.AbsMove(_X, WorkPoint.X_StationPos1);
                if (0 == ret)
                {
                    return 0;
                }
                ret = nMotionCtrl.WaitForStop(_X);
                if (0 == ret)
                {
                    return 0;
                }
                //Y轴移动到抽液位置高
                ret = Bottle_YMoveToFlushPumpingHight(oneRow, loopIndex);
                if (0 == ret)
                {
                    return 0;
                }
            }

            //移动到抽液位置低
            ret = Bottle_YMoveToPumpingLow(oneRow, loopIndex);
            if (0 == ret)
            {
                return 0;
            }
            //非整只
            int waitTime = oneRow.GetMaxPUMPING_WAIT(0);
            Thread.Sleep(waitTime);
            if (true == firstSolvent)
            {
                double[] fzzInVolume = oneRow.GetFlushInVolume(0);
                double[] fzzOutVolume = oneRow.GetFzzOutVolume();
                double[] subML = VolumeSub(fzzInVolume, fzzOutVolume);
                int[] backToBottleFlag = oneRow.GetUsedFlag();
                if (false == AllValueIsZero(subML))
                {
                    //回打到西林瓶
                    int[] FlushInSpeeds = oneRow.GetFlushInSpeed(0);
                    ret = In_AllZWithSpecifiedPercent(backToBottleFlag, subML, FlushInSpeeds);
                    if (0 == ret) { return 0; }
                    mInjectors.SetInjectHadVolume(subML, backToBottleFlag, ZIN);
                }
            }
            else
            {
                double[] fzzOutVolume = oneRow.GetFzzOutVolume();
                int[] speedPercents = oneRow.GetFlushOutSlowSpeed(0);
                int[] validCol = oneRow.GetUsedFlag();
                ret = Out_AllZWithSpecifiedPercent(validCol, fzzOutVolume, speedPercents);
                if (0 == ret) { return 0; }
                mInjectors.SetInjectHadVolume(fzzOutVolume, validCol);
            }

            //ZZ轴移动到安全位置
            ret = Bottle_YPullOutToSafe(oneRow); if (ret == 0) { return 0; }
            for (int i = 0; i < DeviceConfig.StationColNum; i++)
            {
                if ((oneRow.RowStations[i].UsedFlag == 1))
                {
                    if (oneRow.RowStations[i].adviceAndDrug.Enable == 1)
                    {
                        float realdose = (oneRow.RowStations[i].adviceAndDrug.adviceDrug[0].REALDOSE);
                        RemainDrugDose[i] = RemainDrugDose[i] - realdose;
                    }
                }
            }

            //回打溶媒
            int[] solventValidCol = mInjectors.GetHadVolumeFlag();
            ret = Flush_SolventInAndPullInjector(oneRow, solventValidCol, 0);
            if (ret == 0) { return 0; }
            //移动到放药位置
            ret = MoveToPutDrugPos();
            if (0 == ret)
            {
                return 0;
            }
            if (WorkConfig.EnableSolventJaw == 1)
            {
                cDJ.OpenAndCloseJaw(0, 0);
            }

            //判断西林瓶内剩余量是否都为零
            if (BottleRemainIsZero() == 1)
            {
                //西林瓶内没有剩余药液
                HaveBottleInDevice = false;
                cDJ.OpenAndCloseJaw(1, djClosePosIndex);
                ResetRemainDrugDose();
            }
            return 1;
        }

        //判断西林瓶内的剩余量是否都为零
        public long BottleRemainIsZero()
        {
            for (int i = 0; i < DeviceConfig.StationColNum; i++)
            {
                if (RemainDrugDose[i] > 0)
                {
                    return 0;
                }
            }
            return 1;
        }

        private long Surplus_MoveAndExtractSolvent(COneRowStation oneRow)
        {
            long ret = 0;
            SetRunState("开始执行抽溶媒动作");
            //判断所有的列是否要抽取溶媒
            bool HaveSolvent = oneRow.HaveDrug();
            if (true == HaveSolvent)
            {
                //需要抽取溶媒，移动X轴到抽取溶媒位置
                nMotionCtrl.WorkPointID = 1;
                ret = nMotionCtrl.AbsMove(_X, oneRow.XPos);
                if (0 == ret)
                {
                    return 0;
                }
                //等待X轴移动到抽溶媒位置结束
                ret = nMotionCtrl.WaitForStop(); if (0 == ret) { return 0; }
                if (0 == ret)
                {
                    return 0;
                }
                bool extractSolventOkFlag = false;
                while (!extractSolventOkFlag)
                {
                    ret = Surplus_ExtractSolvent(oneRow);
                    if ((0 == ret))
                    {
                        if ((nMotionCtrl.ExitType == 2))
                        {
                            //选择则了退出当前动作，并且Y轴移动到了0点位值
                            //Y轴移动到安全位置
                            //MessageBoxResult mbr = MessageBox.Show("抽取溶媒的过程中出现异常，是否重新抽取溶媒,如果重新抽取溶媒，请打开急停按钮", "操作选择", MessageBoxButton.YesNo);

                            ButtonResult mbr = ButtonResult.Yes;//
                            Application.Current.Dispatcher.Invoke(
                            (Action)delegate ()
                            {
                                _dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={"抽取溶媒的过程中出现异常，是否重新抽取溶媒,如果重新抽取溶媒，请打开急停按钮"}"), r =>
                                {
                                    mbr = r.Result;
                                });
                            });
                            if (mbr == ButtonResult.Yes)
                            {
                                extractSolventOkFlag = false;
                                nMotionCtrl.ExitType = 0;
                                //判断急停按钮是否打开
                                ret = ret = WaitEmgOpen();
                                if (0 == ret)
                                {
                                    return 0;
                                }
                            }
                            else
                            {
                                //选择了不继续抽溶媒，而是直接退出
                                nMotionCtrl.ExitType = 3;
                                return 0;
                            }
                        }
                        else
                        {
                            //选择的是直接退出配药动作
                            return 0;
                        }
                    }
                    else
                    {
                        //
                        nMotionCtrl.ExitType = 0;
                        extractSolventOkFlag = true;
                    }
                }
            }
            return 1;
        }

        private long Surplus_ExtractSolvent(COneRowStation oneRow)
        {
            int loopIndex = 0;
            long ret = 0;
            int[] validCol = oneRow.GetUsedFlag();
            //移动Y轴到要抽溶媒的高度
            ret = Solvent_Plugin(oneRow.UsedSolvent); if (0 == ret) { return 0; }

            //抽出启用站的溶媒
            ret = Surplus_ExtractUsedSolvent(oneRow, loopIndex);
            if (0 == ret)
            {
                return 0;
            }
            Thread.Sleep(1000);
            //Y轴移动到安全高度，拔针
            ret = Solvent_PlugOutSafe(oneRow.UsedSolvent); if (0 == ret) { return 0; }
            return 1;
        }

        //抽出指定mL的溶媒
        private long Surplus_ExtractUsedSolvent(COneRowStation oneRow, int loopIndex)
        {
            long ret = 0;
            int[] fzzFlag = oneRow.GetFZZFlag();
            double[] OutMl = oneRow.GetFlushOutSolventVolume(fzzFlag, loopIndex);
            int[] speed = oneRow.GetOutSolventSpeed();
            int[] validCol = oneRow.GetUsedFlag();
            ret = Out_AllZWithSpecifiedPercent(validCol, OutMl, speed);
            if (0 == ret) { return 0; }
            mInjectors.SetInjectHadVolume(OutMl, validCol);
            return 1;
        }

        private long WetherNeedPullOutSolvent()
        {
            for (int i = 0; i < DeviceConfig.StationColNum; i++)
            {
                if (RemainDrugDose[i] > 0)
                {
                    return 0;//不需要抽取溶媒
                }
            }
            return 1;//需要抽取溶媒
        }

        private long Surplus_AtLastPumpingAllDrugSovent(COneRowStation oneRow, int loopIndex)
        {
            //冲刷动作完成之后，注射器的位置在冲刷低位
            SetRunState("结余模式：慢速抽出剩余部分");
            long ret = 0;
            int[] validCol = oneRow.GetUsedFlag();

            //在负压的情况下打入空气
            double[] flushInAire = oneRow.GetFLUSH_AIRE(0);
            double maxFlushInAire = GetMaxValue(flushInAire);
            int[] pressure = oneRow.GetPOSITIVE_PRESSURE();
            int maxPressure = GetMaxValue(pressure);
            //获取注入空气标志位
            int[] inAirFlag = oneRow.GetFlushInAireFlag(validCol, 0);
            if (false == AllValueIsZero(inAirFlag))
            {
                //负压，有可能抽液不干净，拔针，注射器内抽取空气，打入西林瓶
                //非整只的，不用注入空气，也不用
                ret = Flush_InAir(oneRow, inAirFlag, 0);
                if (0 == ret)
                {
                    return 0;
                }
            }

            //移动Y轴到抽液高度低
            ret = Bottle_YMoveToPumpingLow(oneRow, loopIndex);
            if (0 == ret) { return 0; }
            int maxPumpWaitTime = oneRow.GetMaxPUMPING_WAIT(0);// GetMaxValue(pumpingWait);
            Thread.Sleep(maxPumpWaitTime);
            if (maxPressure < normalPressure)
            {
                //正压，需要再次将注射器插入瓶子
                ret = Bottle_YMoveToPumpingLow(oneRow, 0);
                if (0 == ret) { return 0; }
                ret = Flush_RepetitivePushAndPull(oneRow, validCol, 0);
                if (0 == ret) { return 0; }
                //正压采用同步抽液
                ret = SychronizationPullOut(oneRow, validCol, 0);
                if (0 == ret) { return 0; }
            }
            else
            {
                //常压，负压一次抽完
                bool[] IsLastBottle = new bool[MaxColPointCount];
                ret = PullOutAdditionalAndAir(oneRow, validCol, 0, IsLastBottle);
                if (0 == ret) { return 0; }
                ret = Flush_RepetitivePushAndPull(oneRow, validCol, 0);
                if (0 == ret) { return 0; }
            }
            ret = Bottle_YPullOutToSafe(oneRow);
            if (ret == 0) { return 0; }
            return 1;
        }

        #endregion 剂量相同的结余模式

        #endregion 结余模式

        #region 冲刷函数

        private double[] InjectorHadAirVolume = new double[MaxColPointCount];//冲刷自一次注入空气体积

        private long MoveAndFlush(COneRowStation oneRow, int[] validCol, int row, int dmLoopIndex, int StartRow = 1)
        {
            long ret = 0;
            ret = Bottle_XMoveToFlushPos(oneRow);
            if (0 == ret) { return 0; }
            //进行药品溶解动作
            ret = HP_FlushOneRowDrug(oneRow, validCol, row, dmLoopIndex);
            if (0 == ret)
            {
                return 0;
            }
            return 1;
        }

        private long Surplus_MoveAndFlush(COneRowStation oneRow)
        {
            int[] validCol = oneRow.GetUsedFlag();
            int row = 1;
            int dmLoopIndex = 0;
            int StartRow = 1;
            return MoveAndFlush(oneRow, validCol, row, dmLoopIndex, StartRow);
        }

        //这个函数需要添加判断，注射器的容积是否够用？？？？？？？？？？
        private long HP_FlushOneRowDrug(COneRowStation oneRow, int[] validCol, int row, int dmLoopIndex)
        {
            long ret = 0;
            //移动到冲刷注入高度,添加视觉检测
            //添加判断，西林瓶有没有漏放
            ret = Bottle_YMoveToFlushHight(oneRow);
            if (0 == ret) { return 0; }
            bool okflag = InspectBottle(oneRow);
            if (false == okflag)
            {
                return 0;
            }
            //获取循环册数
            int[] FlushLoopCounts = oneRow.GetFlushCount(row, dmLoopIndex, validCol);//获取每站冲刷次数
            int maxFlushLoopCount = GetMaxValue(FlushLoopCounts);//获取最大冲刷次数
            //每个站，冲刷次数可能不相等，获取每一站，每次冲刷是否启用
            List<int[]> multyFlushLoopFlag = GetLoopPorpertyEnableFlag(maxFlushLoopCount, FlushLoopCounts, validCol);
            //因为有3种冲刷模式，所以，要循环3次
            for (int flushMethod = 0; flushMethod < 4; flushMethod++)
            {
                int[] flushMethodsFlag = oneRow.GetFlushMethodFlag(dmLoopIndex, flushMethod, validCol);
                bool disabledMethod = AllValueIsZero(flushMethodsFlag);
                if (disabledMethod == true)
                {
                    //药品属性里面没有当前的冲刷模式，1：低处冲刷，2：高处冲刷，3：低高冲刷
                    continue;
                }
                else
                {
                    //循环冲刷
                    for (int flushLoopIndex = 0; flushLoopIndex < maxFlushLoopCount; flushLoopIndex++)
                    {
                        int[] oneFlushLoopFlag = multyFlushLoopFlag[flushLoopIndex];

                        if (0 == flushLoopIndex)
                        {
                            ret = FirstFlushIn(oneRow, validCol, dmLoopIndex, flushLoopIndex, flushMethodsFlag, flushMethod);
                        }
                        else
                        {
                            ret = FlushIn(oneRow, validCol, dmLoopIndex, flushLoopIndex, flushMethod, oneFlushLoopFlag, flushMethodsFlag);
                        }
                        if (0 == ret) { return 0; }
                        //检测Z轴是否都在原点位置
                        //ret = DetectionAtZeroPos(oneRow, validCol);
                        //if (0 == ret) { return 0; }
                        //获取最后一次冲刷标志位
                        int[] LastFlushFlag = GetLastFlushFlag(FlushLoopCounts, flushLoopIndex);
                        ret = FlushOut(oneRow, validCol, dmLoopIndex, flushLoopIndex, oneFlushLoopFlag, flushMethodsFlag, LastFlushFlag);
                        if (0 == ret) { return 0; }
                    }
                }
            }
            return 1;
        }

        private long DetectionAtZeroPos(COneRowStation oneRow, int[] validCol)
        {
            long ret = 0;
            bool[] needHome = new bool[MaxColPointCount];
            ret = nMotionCtrl.WaitForStop();
            ret = nMotionCtrl.GetPos();
            bool[] needTest = new bool[MaxColPointCount];

            for (int col = 0; col < StationColNum; col++)
            {
                if ((oneRow.RowStations[col].UsedFlag == 1) && (validCol[col] == 1))
                {
                    int axisID = col + 2;
                    if (nMotionCtrl.AllAxisPos[axisID] == 0)
                    {
                        LogHelper.Info("轴" + axisID + "当前位置在0位，需要检测传感器，判断电机是否堵转！");
                        //该轴在位置0，检测有没有感应到传感器
                        //读取IO信号的状态，
                        bool LimitState = false;
                        int AxisID = _Z + col;
                        nMotionCtrl.GetLimitState(AxisID, LmtType.Nlmt, ref LimitState);
                        if (false == LimitState)
                        {
                            LogHelper.Info("轴" + axisID + "电机发生堵转！需要回零！");
                            //没有感应到传感器，需要移动到限位在停止
                            for (short j = 0; j < 80; j++)
                            {
                                ret = nMotionCtrl.RelMove(AxisID, -1);
                                if (0 == ret)
                                {
                                    return 0;
                                }
                                ret = nMotionCtrl.WaitForStop(); if (0 == ret) { return 0; }
                                nMotionCtrl.GetLimitState(AxisID, LmtType.Nlmt, ref LimitState);
                                if (true == LimitState)
                                {
                                    break;
                                }
                            }
                            needHome[col] = true;
                        }
                        else
                        {
                            needHome[col] = false;
                        }
                    }
                }
                else
                {
                    needHome[col] = false;
                }
            }

            //ZUV,离开限为，并将当前位置清零
            for (short i = 0; i < StationColNum; i++)
            {
                if ((oneRow.RowStations[i].UsedFlag == 1) && (validCol[i] == 1))
                {
                    if (true == needHome[i])
                    {
                        int axisID = _Z + i;
                        LogHelper.Info("轴" + axisID + "因电机堵转，执行回零动作！");
                        //只要又一个需要回零，则全部回零，开启线程回零
                        ret = nMotionCtrl.StartHome(axisID);
                        if (0 == ret)
                        {
                            return 0;
                        }
                        LogHelper.Info("轴" + axisID + "因电机堵转，回零动作完成！");
                    }
                }
            }
            return 1;
        }

        private List<int[]> GetLoopPorpertyEnableFlag(int maxFlushLoopCount, int[] FlushLoopCounts)
        {
            List<int[]> loopFlag = new List<int[]>();
            for (int loopCountIndex = 0; loopCountIndex < maxFlushLoopCount; loopCountIndex++)
            {
                int[] oneLoopFlag = new int[MaxColPointCount];
                for (int col = 0; col < 6; col++)
                {
                    if (loopCountIndex < FlushLoopCounts[col])
                    {
                        oneLoopFlag[col] = 1;
                    }
                    else
                    {
                        oneLoopFlag[col] = 0;
                    }
                }
                loopFlag.Add(oneLoopFlag);
            }
            return loopFlag;
        }

        private List<int[]> GetLoopPorpertyEnableFlag(int maxFlushLoopCount, int[] FlushLoopCounts, int[] validCol)
        {
            List<int[]> loopFlag = new List<int[]>();
            for (int loopCountIndex = 0; loopCountIndex < maxFlushLoopCount; loopCountIndex++)
            {
                int[] oneLoopFlag = new int[MaxColPointCount];
                for (int col = 0; col < 6; col++)
                {
                    if (loopCountIndex < FlushLoopCounts[col])
                    {
                        if (validCol[col] == 1)
                        {
                            oneLoopFlag[col] = 1;
                        }
                        else
                        {
                            oneLoopFlag[col] = 0;
                        }
                    }
                    else
                    {
                        oneLoopFlag[col] = 0;
                    }
                }
                loopFlag.Add(oneLoopFlag);
            }
            return loopFlag;
        }

        //第一次冲刷注入
        private long FirstFlushIn(COneRowStation oneRow, int[] validCol, int dmLoopIndex, int flushLoopIndex, int[] flushMethodsFlag, int flushMethod)
        {
            long ret = 0;
            ret = AdditionalAireIn(oneRow, validCol, dmLoopIndex, flushLoopIndex);
            if (0 == ret) { return 0; }
            double[] viscosityInVolume = new double[MaxColPointCount];
            ret = ViscosityFlushIn(oneRow, validCol, ref viscosityInVolume, dmLoopIndex, flushLoopIndex, flushMethodsFlag);
            if (0 == ret) { return 0; }
            double[] bubbleInVolume = new double[MaxColPointCount];
            ret = BubbleFlushIn(oneRow, validCol, ref bubbleInVolume, dmLoopIndex, flushLoopIndex, flushMethodsFlag);
            if (0 == ret) { return 0; }
            ret = FlushInRemainningVolume(oneRow, validCol, viscosityInVolume, bubbleInVolume, dmLoopIndex, flushLoopIndex, flushMethodsFlag, flushMethod);
            if (0 == ret) { return 0; }
            return 1;
        }

        //注入注射器多抽的空气
        private long AdditionalAireIn(COneRowStation oneRow, int[] validCol, int dmLoopIndex, int flushLoopIndex)
        {
            long ret = 0;
            if (flushLoopIndex == 0)
            {
                ret = Bottle_YMoveToFlushHight(oneRow);
                if (0 == ret) { return 0; }
                int[] flushInSpeed = oneRow.GetFlushInAirSpeed(dmLoopIndex);
                In_AllZWithSpecifiedPercent(validCol, mInjectors.InjectorHadAirVolume, flushInSpeed);
                if (0 == ret) { return 0; }
                //排除注射器内的空气
                mInjectors.ResetInjectorHadAirVolume(validCol);
            }
            return 1;
        }

        //粘稠注入
        private long ViscosityFlushIn(COneRowStation oneRow, int[] validCol, ref double[] inVolume, int dmLoopIndex, int flushLoopIndex, int[] flushMethodFlags)
        {
            long ret = 0;
            if (flushLoopIndex != 0)
            {
                return 1;
            }
            if (dmLoopIndex != 0)
            {
                return 1;
            }

            double[] azSpeed = new double[MaxColPointCount];
            int[] ViscositysUsedFlag = oneRow.GetViscosityFlag();//获取粘稠启用标志位
            bool allDisableViscosity = AllValueIsZero(ViscositysUsedFlag);
            if (allDisableViscosity == true)
            {
                return 1;
            }
            //粘稠冲刷只支持在底部冲刷
            if ((allDisableViscosity != true) && (flushLoopIndex == 0))
            {
                double[] ViscosityInVolume = oneRow.GetViscosityInVolume(dmLoopIndex);
                if (true == AllValueIsZero(ViscosityInVolume))
                {
                    return 1;
                }
                ret = Bottle_YMoveToFlushLow(oneRow, dmLoopIndex);
                if (0 == ret) { return 0; }
                //药品粘稠，只在第一次循环，的第一次冲涮才有效
                int[] ViscosityFlushInSpeeds = oneRow.GetViscosityFlushInSpeed(dmLoopIndex);
                azSpeed = SetAllZAxisSpeedByPercent(ViscosityFlushInSpeeds);

                for (short col = 0; col < StationColNum; col++)
                {
                    //有的通道并不需要粘稠冲涮
                    if ((validCol[col] == 1) && (ViscositysUsedFlag[col] == 1) && (flushMethodFlags[col] == 1))
                    {
                        int AxisID = (_Z + col);
                        //注入容积
                        ret = In_Z(AxisID, ViscosityInVolume[col], azSpeed[col]);//冲入液体
                        if (0 == ret)
                        {
                            return 0;
                        }
                        inVolume[col] = ViscosityInVolume[col];//记录注入的容积数值
                    }
                }
                ret = nMotionCtrl.WaitForStop();
                if (0 == ret) { return 0; }
                //设置注射器内还有液体容积
            }
            return 1;
        }

        //气泡注入
        private long BubbleFlushIn(COneRowStation oneRow, int[] validCol, ref double[] inVolume, int dmLoopIndex, int flushLoopIndex, int[] flushMethodFlags)
        {
            long ret = 0;
            if (flushLoopIndex != 0)
            {
                return 1;
            }
            if (dmLoopIndex != 0)
            {
                return 1;
            }

            double[] azSpeed = new double[MaxColPointCount];
            int[] PropertyUsedFlag = oneRow.GetBubbleFlag();//获取中度气泡启用标志位
            bool allDisableFlag = AllValueIsZero(PropertyUsedFlag);
            if (true == allDisableFlag)
            {
                return 1;
            }
            //起泡冲刷只支持在底部冲刷
            if ((allDisableFlag != true) && (flushLoopIndex == 0))
            {
                double[] FlushinVolume = oneRow.GetFlushInVolume(dmLoopIndex);//获取冲刷注入容积
                double[] ViscosityInVolume = oneRow.GetViscosityInVolume(dmLoopIndex);//粘稠注入容积
                //获取剩下需要注入的容积
                double[] bubbleInVolume = VolumeSub(FlushinVolume, ViscosityInVolume);
                if (true == AllValueIsZero(bubbleInVolume))
                {
                    return 1;
                }
                ret = Bottle_YMoveToFlushLow(oneRow, dmLoopIndex);
                if (0 == ret) { return 0; }
                //药品粘稠，只在第一次循环，的第一次冲涮才有效
                int[] inSpeeds = oneRow.GetBubbleFlushInSpeed(dmLoopIndex);
                azSpeed = SetAllZAxisSpeedByPercent(inSpeeds);

                for (short col = 0; col < StationColNum; col++)
                {
                    //有的通道并不需要粘稠冲涮
                    if ((validCol[col] == 1) && (PropertyUsedFlag[col] == 1) && (flushMethodFlags[col] == 1))
                    {
                        int AxisID = (_Z + col);
                        //注入容积
                        ret = In_Z(AxisID, bubbleInVolume[col], azSpeed[col]);//冲入液体
                        if (0 == ret)
                        {
                            return 0;
                        }
                        inVolume[col] = bubbleInVolume[col];
                    }
                }
                ret = nMotionCtrl.WaitForStop();
                if (0 == ret) { return 0; }
                //设置注射器内还有液体容积
            }
            return 1;
        }

        private long FlushInRemainningVolume(COneRowStation oneRow, int[] validCol, double[] inViscosityVolume, double[] inBubbleVolume, int dmLoopIndex, int flushLoopIndex, int[] flushMethodFlags, int FlushMethod)
        {
            long ret = 0;
            if (flushLoopIndex != 0)
            {
                return 1;
            }
            double[] azSpeed = new double[MaxColPointCount];
            double[] flushInVolume = oneRow.GetFlushInVolume(dmLoopIndex);
            double[] hadInVolume = VolumeAdd(inViscosityVolume, inBubbleVolume);
            double[] inVolume = VolumeSub(flushInVolume, hadInVolume);
            if (AllValueIsZero(inVolume) == true)
            {
                return 1;
            }
            int[] inSpeed = oneRow.GetFlushInSpeed(dmLoopIndex);
            azSpeed = SetAllZAxisSpeedByPercent(inSpeed);
            ret = MoveYToFlushInheightByFlushMethod(oneRow, FlushMethod, dmLoopIndex, flushLoopIndex, validCol, inVolume);
            if (0 == ret) { return 0; }
            for (short col = 0; col < StationColNum; col++)
            {
                //有的通道并不需要粘稠冲涮
                if ((validCol[col] == 1) && (flushMethodFlags[col] == 1))
                {
                    int AxisID = (_Z + col);
                    //注入容积
                    ret = In_Z(AxisID, inVolume[col], azSpeed[col]);//冲入液体
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }
            ret = nMotionCtrl.WaitForStop();
            if (0 == ret) { return 0; }
            return 1;
        }

        private long FlushIn(COneRowStation oneRow, int[] validCol, int dmLoopIndex, int flushLoopIndex, int FlushMethod, int[] oneLoopFlushFlag, int[] flushMethodFlag)
        {
            long ret = 0;
            //不是第一次，注入的容积=flushInVolume or 中度气泡的冲刷抽出容积
            //中度或重度气泡
            double[] FlushingOutVolumes = oneRow.GetFlushOutVolume(dmLoopIndex);//起泡冲刷抽出的溶媒体积
            double[] FlushinVolumes = oneRow.GetFlushInVolume(dmLoopIndex);//冲刷注入的溶媒体积

            int[] FlushInSpeed = oneRow.GetFlushInSpeed(dmLoopIndex);
            int[] BubbleFlag = oneRow.GetBubble();
            double[] azSpeed = SetAllZAxisSpeedByPercent(FlushInSpeed);
            double[] inVolume = GetInVolume(oneRow, validCol, dmLoopIndex);
            ret = MoveYToFlushInheightByFlushMethod(oneRow, FlushMethod, dmLoopIndex, flushLoopIndex, validCol, inVolume);
            if (0 == ret) { return 0; }
            for (short col = 0; col < StationColNum; col++)
            {
                if ((validCol[col] == 1) && (oneLoopFlushFlag[col] == 1) && (flushMethodFlag[col] == 1))
                {
                    //满足以下条件，1，该站启用，2，该站在允许的冲刷次数内，该站是指定的充数模式
                    int AxisID = (_Z + col);
                    double aIn = 0;
                    if (BubbleFlag[col] > 1)
                    {
                        aIn = FlushingOutVolumes[col];//中度气泡
                    }
                    else
                    {
                        aIn = FlushinVolumes[col];
                    }
                    ret = In_Z(AxisID, aIn, azSpeed[col]);//冲入液体
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }
            ret = nMotionCtrl.WaitForStop();
            if (0 == ret) { return 0; }
            return 1;
        }

        private double[] GetInVolume(COneRowStation oneRow, int[] validCol, int dmLoopIndex)
        {
            double[] inVolume = new double[MaxColPointCount];
            double[] FlushingOutVolumes = oneRow.GetFlushOutVolume(dmLoopIndex);//起泡冲刷抽出的溶媒体积
            double[] FlushinVolumes = oneRow.GetFlushInVolume(dmLoopIndex);//冲刷注入的溶媒体积

            int[] FlushInSpeed = oneRow.GetFlushInSpeed(dmLoopIndex);
            int[] BubbleFlag = oneRow.GetBubble();

            for (short col = 0; col < StationColNum; col++)
            {
                if ((validCol[col] == 1))
                {
                    double aIn = 0;
                    if (BubbleFlag[col] > 1)
                    {
                        aIn = FlushingOutVolumes[col];//中度气泡
                    }
                    else
                    {
                        aIn = FlushinVolumes[col];
                    }
                    inVolume[col] = aIn;
                }
            }
            return inVolume;
        }

        private long FlushOut(COneRowStation oneRow, int[] validCol, int dmLoopIndex, int flushLoopIndex, int[] oneLoopFlushFlag, int[] flushMethodFlag, int[] LastFlag)
        {
            long ret = 0;
            //不是第一次，注入的容积=flushInVolume or 中度气泡的冲刷抽出容积
            //中度或重度气泡
            double[] FlushingOutVolumes = oneRow.GetFlushOutVolume(dmLoopIndex);//起泡冲刷抽出的溶媒体积
            double[] FlushinVolumes = oneRow.GetFlushInVolume(dmLoopIndex);//冲刷注入的溶媒体积

            int[] FlushOutSpeed = oneRow.GetFlushOutSpeed(dmLoopIndex);
            int[] BubbleFlag = oneRow.GetBubble();
            //Y轴移动抽取液体高度
            ret = Bottle_YMoveToFlushPumpingHight(oneRow, dmLoopIndex);
            if (0 == ret) { return 0; }
            //添加抽液前等待，条件，有气泡
            bool haveBubble = AllValueIsZero(BubbleFlag);
            bool isLastFlush = AllValueIsZero(LastFlag);
            if ((false == haveBubble) && (false == isLastFlush))
            {
                //添加冲刷抽液等待
                double[] FlushOutWait = oneRow.GetFlushOutLastWait(dmLoopIndex);
                double maxFlushOutWait = GetMaxValue(FlushOutWait);
                Thread.Sleep((int)(maxFlushOutWait * 1000));
            }
            else
            {
                double[] FlushOutWait = oneRow.GetFlushOutWait(dmLoopIndex);
                double maxFlushOutWait = GetMaxValue(FlushOutWait);
                Thread.Sleep((int)(maxFlushOutWait * 1000));
            }
            double[] azSpeed = SetAllZAxisSpeedByPercent(FlushOutSpeed);
            //循环抽出溶媒,设置抽出速度
            for (short col = 0; col < StationColNum; col++)
            {
                if ((validCol[col] == 1) && (oneLoopFlushFlag[col] == 1) && (flushMethodFlag[col] == 1))
                {
                    int AxisID = _Z + col;
                    double aOut = 0;
                    if (LastFlag[col] == 0)
                    {
                        if (BubbleFlag[col] > 1)
                        {
                            aOut = FlushingOutVolumes[col];//中度气泡
                        }
                        else
                        {
                            aOut = FlushinVolumes[col];
                        }
                    }
                    else
                    {
                        aOut = FlushinVolumes[col];
                    }
                    ret = Out_Z(AxisID, aOut, azSpeed[col]);//移动要抽出液体的高度
                    if (0 == ret)
                    {
                        return 0;
                    }
                }
            }

            //等待抽取动作停止
            ret = nMotionCtrl.WaitForStop();
            if (0 == ret) { return 0; }
            return 1;
        }

        private int[] GetLastFlushFlag(int[] FlushLoopCounts, int flushLoopIndex)
        {
            //获取最后一次冲刷标志位
            int[] LastFlushFlag = new int[MaxColPointCount];
            for (int col = 0; col < StationColNum; col++)
            {
                if (flushLoopIndex == (FlushLoopCounts[col] - 1))
                {
                    LastFlushFlag[col] = 1;
                }
                else
                {
                    LastFlushFlag[col] = 0;
                }
            }
            return LastFlushFlag;
        }

        private long MoveYToFlushInheightByFlushMethod(COneRowStation oneRow, int FlushMethod, int dmLoopIndex, int flushLoopIndex, int[] inValidCol, double[] inVolume)
        {
            long ret = 0;
            double flushLowPos = GetFlushLowPos(oneRow, dmLoopIndex);
            if (FlushMethod == 0)
            {
                //在低处配药
                ret = Bottle_YMoveToFlushLow(oneRow, dmLoopIndex);
                if (0 == ret) { return 0; }
            }
            else if (FlushMethod == 1)
            {
                //高处配药
                ret = Bottle_YMoveToFlushHight(oneRow);
                if (0 == ret) { return 0; }
            }
            else if (FlushMethod == 2)
            {
                //运动配药
                ret = Bottle_YMoveToFlushLow(oneRow, dmLoopIndex);
                if (0 == ret) { return 0; }
                double YMoveSpeed = GetYSpeed_Flush(oneRow, flushLoopIndex, inValidCol, inVolume, flushLowPos);
                //Y轴从低处，向高处运动
                ret = nMotionCtrl.AbsMove(_Y, YMoveSpeed, WorkPoint.Y_FlushHeightHight);
                if (0 == ret) { return 0; }
            }
            else if (FlushMethod == 3)
            {
                //混合配药
                if (flushLoopIndex % 2 == 0)
                {
                    //在低处配药
                    ret = Bottle_YMoveToFlushLow(oneRow, dmLoopIndex);
                    if (0 == ret) { return 0; }
                }
                else if (flushLoopIndex % 2 == 1)
                {
                    //高处
                    ret = Bottle_YMoveToFlushHight(oneRow);
                    if (0 == ret) { return 0; }
                }
                if (0 == ret)
                {
                    return 0;
                }
            }
            else
            {
                //在低处配药
                ret = Bottle_YMoveToFlushLow(oneRow, dmLoopIndex);
                if (0 == ret) { return 0; }
            }
            return 1;
        }

        private double GetYSpeed_Flush(COneRowStation oneRow, int dmLoopIndex, int[] inValidCol, double[] inVolume, double flushLowPos)
        {
            double maxZTime = GetMaxFlushInUsedTime(oneRow, dmLoopIndex, inValidCol, inVolume);
            //计算Y轴要移动的距离
            double ysub = WorkPoint.Y_FlushHeightHight - flushLowPos;
            //计算Y轴需要的速度
            double ynspeed = (ysub / maxZTime) * 1;
            return ynspeed;
        }

        //获取同步抽出，Y的速度
        private double GetYSpeed_SYSPullOut(COneRowStation oneRow, int dmLoopIndex, int[] inValidCol, double[] inVolume, double flushLowPos)
        {
            double maxZTime = GetMaxPullOutAdditionAirUsedTime(oneRow, dmLoopIndex, inValidCol, inVolume);
            //计算Y轴要移动的距离
            double ysub = flushLowPos - WorkPoint.Y_BottleStartPunctureHeight;
            //计算Y轴需要的速度
            double ynspeed = (int)(ysub / maxZTime) + 1;
            return ynspeed;
        }

        //视觉监测
        private bool InspectBottle(COneRowStation ColStation)
        {
            if (1 == DeviceConfig.VisualInspection)
            {
                int[] usedFlag = ColStation.GetUsedFlag();
                int stationCount = DeviceConfig.StationColNum;
                stationCount = 4;
                //_bottleInspcet.InspectBottle(stationCount, usedFlag);
            }

            return true;
        }

        #endregion 冲刷函数

        #region 抽取剩余液体函数

        private long PullOutVolumeAtLast(COneRowStation oneRow, int[] inValidCol, int dmLoopIndex, bool[] IsLastBottle)
        {
            //冲刷动作完成之后，注射器的位置在冲刷低位
            SetRunState("开始慢速抽出剩余药液");
            long ret = 0;

            int[] backToBottleFlag = oneRow.GetFZZBackToBottleFlag(inValidCol, dmLoopIndex);
            //获取注射器回打到西林瓶的容积的容积，非整只回打计算的容积，整支的，回打为0
            double[] backToBottleML = GetBackToBottleVolume(oneRow, backToBottleFlag);
            //抽取定量的药液
            if (false == AllValueIsZero(backToBottleML))
            {
                int[] FlushInSpeeds = oneRow.GetFlushInSpeed(dmLoopIndex);
                ret = In_AllZWithSpecifiedPercent(backToBottleFlag, backToBottleML, FlushInSpeeds);
                if (0 == ret) { return 0; }
                mInjectors.SetInjectHadVolume(backToBottleML, backToBottleFlag, ZIN);
            }
            //在负压的情况下打入空气
            double[] flushInAire = oneRow.GetFLUSH_AIRE(dmLoopIndex);
            double maxFlushInAire = GetMaxValue(flushInAire);
            int[] pressure = oneRow.GetPOSITIVE_PRESSURE();
            int maxPressure = GetMaxValue(pressure);
            //获取注入空气标志位
            int[] inAirFlag = oneRow.GetFlushInAireFlag(inValidCol, dmLoopIndex);
            if (false == AllValueIsZero(inAirFlag))
            {
                //负压，有可能抽液不干净，拔针，注射器内抽取空气，打入西林瓶
                //非整只的，不用注入空气，也不用
                ret = Flush_InAir(oneRow, inAirFlag, dmLoopIndex);
                if (0 == ret)
                {
                    return 0;
                }
            }
            else
            {
                //轻度有气泡，用拔针的方式解决,只要有一个需要拔针，则全部拔针
                int[] lowBubbleFlag = oneRow.GetLowBubbleFlag();
                if (false == AllValueIsZero(lowBubbleFlag))
                {
                    //只要有一个是轻度气泡酒拔针
                    ret = Bottle_PullOutInjectorNoPushAir(oneRow, dmLoopIndex); if (0 == ret) { return 0; }
                }
            }
            //移动Y轴到抽液高度低
            ret = Bottle_YMoveToPumpingLow(oneRow, dmLoopIndex);
            if (0 == ret) { return 0; }
            int maxPumpWaitTime = oneRow.GetMaxPUMPING_WAIT(dmLoopIndex);// GetMaxValue(pumpingWait);
            Thread.Sleep(maxPumpWaitTime);
            int[] pullOutFlag = oneRow.GetPullOutFlag(inValidCol);
            int[] repetiveFlag = oneRow.GetRepetiveFlag(inValidCol);
            if (maxPressure < normalPressure)
            {
                //正压，需要再次将注射器插入瓶子
                ret = Bottle_YMoveToPumpingLow(oneRow, dmLoopIndex);
                if (0 == ret) { return 0; }
                ret = Flush_RepetitivePushAndPull(oneRow, repetiveFlag, dmLoopIndex);
                if (0 == ret) { return 0; }
                //正压采用同步抽液
                ret = SychronizationPullOut(oneRow, pullOutFlag, dmLoopIndex);
                if (0 == ret) { return 0; }
            }
            else
            {
                //常压，负压一次抽完
                //抽出多抽体积和多抽空气体积
                ret = PullOutAdditionalAndAir(oneRow, pullOutFlag, dmLoopIndex, IsLastBottle);
                if (0 == ret) { return 0; }
                ret = Flush_RepetitivePushAndPull(oneRow, repetiveFlag, dmLoopIndex);
                if (0 == ret) { return 0; }
            }
            //在正压，的情况下，将多抽的1.5ml空气排出到当前的瓶子内
            if (maxPressure <= normalPressure)
            {
                //正压或常压打回到当前的瓶子里,在轻度难容和重度难容的情况下，不需要将空气打回到当前瓶子
                int[] drugCountOfOneLoop = oneRow.GetDrugCountOfLoopFlush(dmLoopIndex);
                int maxValue = GetMaxValue(drugCountOfOneLoop);
                if ((maxValue == 2) || (maxValue == 4))
                {
                    //只有在易容的情况下，或中度难容第二次配药的时候，才需要将多抽的1.5ml空气打回到当前瓶子里面
                    //正压，需要再次将注射器插入瓶子
                    ret = Bottle_YMoveToPumpingLow(oneRow, dmLoopIndex);
                    if (0 == ret) { return 0; }
                    double[] outAire = GetAdditionalPullOutAirVolume(oneRow, pullOutFlag, dmLoopIndex);
                    ret = PushInAirAfterFlushOver(oneRow, pullOutFlag, outAire, dmLoopIndex);
                    if (0 == ret) { return 0; }
                }
            }
            ret = Bottle_YPullOutToSafe(oneRow);
            if (ret == 0) { return 0; }
            SetRunState("慢速抽出剩余药液动作结束");
            return 1;
        }

        private long PullOutAdditionalAndAir(COneRowStation oneRow, int[] ivalidCol, int dmLoopIndex, bool[] IsLastBottle)
        {
            long ret = 0;
            int[] validCol = oneRow.GetPullOutFlag(ivalidCol);
            //获取多抽液体
            double[] outAdditional = GetAdditionalPullOutLiquidVolume(oneRow, validCol, dmLoopIndex, IsLastBottle);
            if (false == AllValueIsZero(outAdditional))
            {
                int[] FlushOutSlowSpeeds = oneRow.GetFlushOutSlowSpeed(dmLoopIndex);
                ret = Out_AllZWithSpecifiedPercent(validCol, outAdditional, FlushOutSlowSpeeds);
                if (0 == ret) { return 0; }
                mInjectors.SetInjectHadVolume(outAdditional, validCol);
            }
            //获取多抽空气体积
            double[] outAire = GetAdditionalPullOutAirVolume(oneRow, validCol, dmLoopIndex);
            if (false == AllValueIsZero(outAire))
            {
                int[] FlushOutSlowSpeeds = oneRow.GetFlushOutSlowSpeed(dmLoopIndex);
                ret = Out_AllZWithSpecifiedPercent(validCol, outAire, FlushOutSlowSpeeds);
                if (0 == ret) { return 0; }

                mInjectors.SetInjectorHadAirVolume(outAire, validCol);
            }
            return 1;
        }

        private double[] SubML(double[] AllML, double[] airML)
        {
            double[] subML = new double[MaxColPointCount];
            for (int col = 0; col < StationColNum; col++)
            {
                subML[col] = AllML[col] - airML[col];
                if (subML[col] < 0)
                {
                    subML[col] = 0;
                }
            }
            return subML;
        }

        //Y轴一边移动一边抽取液体，常压拔针漏液问题
        private long SychronizationPullOut(COneRowStation oneRow, int[] iValidCol, int dmLoopIndex)
        {
            //抽残余液体的时候启用慢速度
            long ret = 0;

            int[] FlushOutSlowSpeeds = oneRow.GetFlushOutSlowSpeed(dmLoopIndex);
            //在同步抽取前先抽出部分液体出来
            double[] addtionalML = oneRow.GetADDITIONAL_PUMPING(dmLoopIndex);
            //获取可以抽出的站
            int[] validPullOutAddtionalCol = oneRow.GetPullOutAddtionalFlag(iValidCol);
            //获取有效的多抽体积
            double[] validAddtionalML = GetValidValue(addtionalML, validPullOutAddtionalCol);
            if (false == AllValueIsZero(validAddtionalML))
            {
                ret = Out_AllZWithSpecifiedPercent(validPullOutAddtionalCol, validAddtionalML, FlushOutSlowSpeeds);
                if (0 == ret) { return 0; }
                mInjectors.SetInjectHadVolume(validAddtionalML, validPullOutAddtionalCol);
            }
            //获取多抽空气
            double[] additionalAir = oneRow.GetAdditionalOutAirVolume(dmLoopIndex);
            //获取使用站的多抽空气体积
            double[] validAirML = GetValidValue(additionalAir, validPullOutAddtionalCol);
            if (AllValueIsZero(validAirML) == false)
            {
                //同步抽出多抽空气体积
                ret = SychronizationPullOutSpecifiedML(oneRow, validPullOutAddtionalCol, additionalAir, dmLoopIndex);
                if (0 == ret) { return 0; }
                mInjectors.SetInjectHadVolume(validAirML, validPullOutAddtionalCol);
            }
            return 1;
        }

        //同步抽出指定体积
        private long SychronizationPullOutSpecifiedML(COneRowStation oneRow, int[] iValidCol, double[] ml, int dmLoopIndex)
        {
            long ret = 0;
            double flushLowPos = GetFlushLowPos(oneRow, dmLoopIndex);
            int[] FlushOutSlowSpeeds = oneRow.GetFlushOutSlowSpeed(dmLoopIndex);
            //计算Y轴需要的速度
            double yspeed = GetYSpeed_SYSPullOut(oneRow, dmLoopIndex, iValidCol, ml, flushLowPos);
            // Y 轴向下移动的同时，所有Z轴同时向下运动抽液体，
            nMotionCtrl.NoEMG_AbsMove(_Y, yspeed, WorkPoint.Y_BottleStartPunctureHeight);
            int[] validCol = oneRow.ANDFlag(iValidCol);
            ret = Out_AllZWithSpecifiedPercent(validCol, ml, FlushOutSlowSpeeds);
            if (0 == ret) { return 0; }

            return 1;
        }

        private long Bottle_PullOutInjectorNoPushAir(COneRowStation oneRow, int loopIndex)
        {
            SetRunState("开始执行轻度气泡拔针动作");
            long ret = 0;
            ret = Bottle_YPullOutToStart(oneRow);
            if (0 == ret) { return 0; }
            ret = Bottle_YPlugInToFlushHight(oneRow);
            if (0 == ret) { return 0; }
            return 1;
        }

        #endregion 抽取剩余液体函数

        #region 注入空气函数01

        private long PushInAirAfterFlushOver(COneRowStation oneRow, int[] iValidCol, double[] airML, int dmLoopIndex)
        {
            //排出注射器内都抽部分液体的体积
            SetRunState("开始执行将注射内多抽空气排出的动作");
            long ret = 0;
            //正压或常压
            if (oneRow.UsedDrug.POSITIVE_PRESSURE <= normalPressure)
            {
                //将当前注射器内的空气排到当前的西林瓶内
                int[] FlushInSpeeds = oneRow.GetFlushInSpeed(dmLoopIndex);
                if (false == AllValueIsZero(airML))
                {
                    ret = In_AllZWithSpecifiedPercent(iValidCol, airML, FlushInSpeeds);
                    if (0 == ret) { return 0; }
                    mInjectors.ResetInjectorHadAirVolume(iValidCol);
                }
            }
            return 1;
        }

        //抽液注入空气
        private long Flush_InAir(COneRowStation oneRow, int[] validCol, int dmLoopIndex)
        {
            long ret = 0;
            double[] airml = oneRow.GetFLUSH_AIRE(dmLoopIndex); //要多注入的空气
            int[] inAirSpeed = oneRow.GetFlushInAirSpeed(dmLoopIndex);
            ret = InAir(oneRow, validCol, airml, inAirSpeed);
            if (0 == ret) { return 0; }
            return 1;
        }

        private long InAir(COneRowStation oneRow, int[] validCol, double[] airml, int[] inAirSpeed)
        {
            long ret = 0;
            SetRunState("开始执行负压向西林瓶内打入空气动作");
            bool CanInAire = false;
            CanInAire = InjectorCanInVolume(oneRow, validCol);//判断注射器还有没有剩余的空间来抽取空气
            if (false == CanInAire)
            {
                return 1;
            }
            double[] InjectorResidualVolume = mInjectors.GetInjectResidualVolume();
            ret = InAirUseLoop(oneRow, validCol, InjectorResidualVolume, airml, inAirSpeed);
            if (0 == ret) { return 0; }
            return 1;
        }

        private long InAirUseLoop(COneRowStation oneRow, int[] validCol, double[] InjectorResidualVolume, double[] airml, int[] inAirSpeed)
        {
            long ret = 0;
            List<double[]> loopAir = GetInAirLoopValue(oneRow, InjectorResidualVolume, airml);
            int loopCount = loopAir.Count;
            for (int loop = 0; loop < loopCount; loop++)
            {
                LogHelper.Info("循环注入空气：第" + loop.ToString() + "循环！");
                double[] rowml = loopAir[loop];
                LogHelper.Info("Y轴移动到穿刺起始高度：" + WorkPoint.Y_BottleStartPunctureHeight.ToString());
                ret = YMoveToDestPos(WorkPoint.Y_BottleStartPunctureHeight);
                if (0 == ret) { return 0; }
                //抽空气
                LogHelper.Info("注射器抽空气:");
                ret = Out_ALLZWithWorkSpeed(validCol, rowml);
                if (0 == ret) { return 0; }
                //插入西林瓶
                LogHelper.Info("Y轴移动到抽液高位：" + WorkPoint.Y_PumpHeightHight.ToString());
                ret = Bottle_YMoveToFlushPumpingHight(oneRow, 0);
                if (0 == ret) { return 0; }
                //注入空气
                LogHelper.Info("空气注入西林瓶");
                ret = In_AllZWithSpecifiedPercent(validCol, rowml, inAirSpeed);
                if (0 == ret) { return 0; }
                if (loop == loopCount - 1)
                {
                    //最后一次，注射器在瓶内不动作
                }
                else
                {
                    //不是最后一次，需要拔针继续抽空气,则移动到穿刺起始高度
                    ret = Bottle_YPullOutToStart(oneRow);
                    if (0 == ret) { return 0; }
                }
            }
            return 1;
        }

        #endregion 注入空气函数01

        #region 反复抽液函数

        // 冲刷后的反复抽液
        private long Flush_RepetitivePushAndPull(COneRowStation oneRow, int[] validCol, int dmLoopIndex)
        {
            long ret = 0;
            SetRunState("冲刷后反复多抽");
            //double InjectorResidualMinVolume = oneRow.GetMinResidualVolume(StationColNum);
            //添加循环抽取多次
            int[] outSpeed = oneRow.GetFlushRePullOutSpeed(dmLoopIndex);
            int[] inSpeed = oneRow.GetFlushRePullInSpeed(dmLoopIndex);

            int[] repullCount = oneRow.GetFlushRePullCount(dmLoopIndex);
            int maxRepullCount = GetMaxValue(repullCount);
            //非整只，不支持反复抽液
            double[] volume = oneRow.GetFlushRePullOutVolume(dmLoopIndex);
            double[] validML = GetValidValue(volume, validCol);
            //根据注射器剩余容积，获得可以反复抽液的容积
            double[] allZVloume = GetInjectorCanUsedVolume(validML, validCol);
            if (false == AllValueIsZero(allZVloume))
            {
                double[] waitTime = oneRow.GetFlushRePullPumping_Wait(dmLoopIndex);
                double maxWaitTime = GetMaxValue(waitTime);
                int[] repetiveFlag = oneRow.GetRepetiveFlag(validCol);
                ret = RepetitivePushAndPull(oneRow, repetiveFlag, dmLoopIndex, maxRepullCount, allZVloume, inSpeed, outSpeed, maxWaitTime);
                if (0 == ret) { return 0; }
            }

            return 1;
        }

        //水针反复多抽
        private long SZ_RepetitivePushAndPull(COneRowStation oneRow, int[] usedFlag, int dmLoopIndex)
        {
            return Flush_RepetitivePushAndPull(oneRow, usedFlag, dmLoopIndex);
        }

        #endregion 反复抽液函数

        #region 回抽

        private long RebackPull(COneLoopStations oneLoop)
        {
            long ret = 0;
            int maxPumpBackLoopCount = oneLoop.GetMaxPumpBackLoopCount();
            if ((maxPumpBackLoopCount < 1))
            {
                return 1;
            }
            SetRunState("--------开始回抽--------");
            mInjectors.ResetInjectHadVolume();
            COneRowStation SolventRowStation = oneLoop.MultyRowStation[0];
            int[] PumpBackLoopCount = SolventRowStation.GetPumpBackLoopCount();//获取每一站的回抽循环次数
            List<int[]> enableFlag = GetLoopPorpertyEnableFlag(maxPumpBackLoopCount, PumpBackLoopCount);
            //有的药可能回抽一次，有的药可能要回抽两次
            for (int pumpBackLoopIndex = 0; pumpBackLoopIndex < maxPumpBackLoopCount; pumpBackLoopIndex++)
            {
                bool PullOkFlag = false;
                while (!PullOkFlag)
                {
                    int[] oneLoopEnableFlag = enableFlag[pumpBackLoopIndex];
                    //水针，或者重度气泡的前提下，添加回抽
                    SetRunState("第" + pumpBackLoopIndex.ToString() + "次回抽");
                    ret = PumpBack_OneLoop(oneLoop, oneLoopEnableFlag, pumpBackLoopIndex);
                    if (0 == ret)
                    {
                        if (nMotionCtrl.ExitType == 3)
                        {
                            SetRunState("在配药的过程中，急停按钮被按下，选择了直接退出配药！", LogLevel.Warning);
                            return 0;
                        }
                        else if (nMotionCtrl.ExitType == 2)
                        {
                            //只是选择了退出当前动作，回抽还可以从头再来一次
                            //MessageBoxResult mbr = MessageBox.Show("在回抽的过程中急停按钮被按下，是否重新回抽？", "操作选择", MessageBoxButton.YesNo);
                            ButtonResult mbr = ButtonResult.Yes;//
                            Application.Current.Dispatcher.Invoke(
                            (Action)delegate ()
                            {
                                _dialogService.ShowDialog("AlertDialog", new DialogParameters($"message={"在回抽的过程中急停按钮被按下，是否重新回抽？"}"), r =>
                                {
                                    mbr = r.Result;
                                });
                            });
                            if (mbr == ButtonResult.Yes)
                            {
                                //添加判断，急停按钮是否打开
                                ret = WaitEmgOpen();
                                if (0 == ret)
                                {
                                    return 0;
                                }
                                //FlushOKFlag = false;
                                nMotionCtrl.ExitType = 0;
                                SetRunState("回抽：异常回打溶媒！");
                                ret = PumpBack_SolventInAndPullInjector(SolventRowStation, oneLoopEnableFlag, pumpBackLoopIndex);
                                if (0 == ret)
                                {
                                    return 0;
                                }
                                ret = nMotionCtrl.WaitForStop();
                                if (0 == ret) { return 0; }
                            }
                            else
                            {
                                //是按下急停选择了退出
                                nMotionCtrl.ExitType = 3;
                                SetRunState("回抽：失败退出");
                                return 0;
                            }
                        }
                        else
                        {
                            SetRunState("回抽：失败退出！");
                            return 0;
                        }
                    }
                    else
                    {
                        PullOkFlag = true;
                    }
                }
            }
            SetRunState("--------回抽结束--------");
            return 1;
        }

        //二次抽液，不抽取溶媒，用来解决，气泡过多的情况
        private long PumpBack_OneLoop(COneLoopStations oneLoop, int[] oneLoopEnableIndex, int pumpbackLoopIndex)
        {
            //在添加一个二次只抽液体的功能，相当于抽水针
            long ret = 0;
            int RowStationCount = StationRowNum;
            COneRowStation SolventRowStation = oneLoop.MultyRowStation[0];
            int IncreaseValue = 1;
            int StartRow = 1;
            if (oneLoop.UsedDrug.SOLVENT_FLAG == 2)
            {
                //专用溶媒,回抽从第二行开始
                SetRunState("专用溶媒，回抽药液");
                IncreaseValue = 2;
            }
            else
            {
                SetRunState("普通溶媒，回抽药液");
            }
            StartRow = PumpBack_GetStartRow(oneLoop);//获取回抽起始行
            for (int row = StartRow; row < RowStationCount; row += IncreaseValue)
            {
                //获取1行数据
                COneRowStation oneRow = oneLoop.MultyRowStation[row];
                if (false == oneRow.HaveDrug(oneLoopEnableIndex))
                {
                    //该行没有药，直接退出
                    break;
                }

                int[] haveDrugFlag = oneRow.ANDFlag(oneLoopEnableIndex);
                int[] pumpBackFlag = oneRow.GetPumpbackValidCol(haveDrugFlag);
                if (true == AllValueIsZero(pumpBackFlag))
                {
                    //当前行没有启用的有效列,有可能第一行全是非整只的
                    continue;
                }

                SetRunState("回抽：开始第" + row.ToString() + "行回抽！");
                ret = PumpBack_OneRowPullOut(oneLoop, oneRow, pumpBackFlag, SolventRowStation, row, pumpbackLoopIndex);
                if (0 == ret)
                {
                    return 0;
                }
                SetRunState("回抽：第" + row.ToString() + "回抽结束！");
            }

            //判断注射器内有没有溶媒
            SetRunState("下一行没有西林瓶需要抽液");
            double[] injectorHadVolume = mInjectors.GetInjectResidualVolume();
            bool NeedReback = NeedRebackByInjectors();//通过注射器内的使用容积，判断需不需要回打到溶媒袋
            if (true == NeedReback)
            {
                //注射器内有溶媒
                SetRunState("注射器内有药液，需要回打到溶媒袋！");
                int[] validCol_Solvent = mInjectors.GetHadVolumeFlag();
                ret = PumpBack_SolventInAndPullInjector(SolventRow, validCol_Solvent, 0);
                if (0 == ret) { return 0; }
            }

            ret = nMotionCtrl.WaitForStop();
            if (0 == ret) { return 0; }
            return 1;
        }

        private int PumpBack_GetStartRow(COneLoopStations oneLoop)
        {
            int StartRow = 1;
            int[] fzzFlag = oneLoop.MultyRowStation[1].GetFZZFlag();
            //判断第一行全是非整只
            if (false == AllValueIsZero(fzzFlag))
            {
                //非整只的
                if (true == AllValueIsNotZero(fzzFlag))
                {
                    //所有值都不为零,就是第一行全是非整只的
                    if (oneLoop.UsedDrug.SOLVENT_FLAG == 2)
                    {
                        StartRow = 4;
                    }
                    else
                    {
                        StartRow = 2;
                    }
                }
                else
                {
                    //有的是整只的，有的是非整只的
                    if (oneLoop.UsedDrug.SOLVENT_FLAG == 2)
                    {
                        StartRow = 2;
                    }
                    else
                    {
                        StartRow = 1;
                    }
                }
            }
            else
            {
                //全是整只的
                if (oneLoop.UsedDrug.SOLVENT_FLAG == 2)
                {
                    StartRow = 2;
                }
                else
                {
                    StartRow = 1;
                }
            }
            return StartRow;
        }

        private long PumpBack_OneRowPullOut(COneLoopStations oneLoop, COneRowStation oneDrugRow, int[] validCol, COneRowStation SolventRow, int row, int pumpbackLoopIndex)
        {
            //一次回抽最大20ml
            long ret = 0;
            SetRunState("回抽第" + row.ToString() + "行");
            SetRunState("X轴移动到第" + row.ToString() + "行位置！");
            ret = XBottleMoveToPuctruePos(oneDrugRow.XPos);
            if (0 == ret)
            {
                return 0;
            }
            //回抽注入空气
            LogHelper.Info("回抽注入空气！");
            ret = PumpBack_InAir(oneDrugRow, validCol, pumpbackLoopIndex);
            if (ret == 0) { return 0; }

            //Y轴移动到抽取液体高度，这个地方有个问题，如果注入空气，则注射器在西林瓶内，否则，注射器在西林瓶外侧
            SetRunState("Y轴移动到抽液高度！");
            ret = Bottle_YMoveToPumpingLow(oneDrugRow, pumpbackLoopIndex);
            if (0 == ret) { return 0; }

            //抽液等待
            SetRunState("抽液等待！");
            int waitTime = oneDrugRow.GetMaxPumpBackWait(pumpbackLoopIndex);
            Thread.Sleep(waitTime);
            //添加回抽等待
            SetRunState("Z轴向下运动，抽出药液");
            double[] NeedOutVolume = GetPumpBackOutVolume(oneDrugRow, validCol, pumpbackLoopIndex);
            int[] PumpBackRePullOutSpeeds = oneDrugRow.GetPumpBackRePullOutSpeed(pumpbackLoopIndex);

            ret = Out_AllZWithSpecifiedPercent(validCol, NeedOutVolume, PumpBackRePullOutSpeeds);
            if (0 == ret) { return 0; }
            //设置注射器内的剩余容积,还要加上上一行的使用容积
            mInjectors.SetInjectHadVolume(NeedOutVolume, validCol);
            //反复抽液,添加判断能不能反复抽拉
            SetRunState("反复多抽");
            ret = PumpBack_RepetitivePushAndPull(oneDrugRow, validCol, pumpbackLoopIndex);
            if (0 == ret) { return 0; }

            //移动到安全位置
            SetRunState("Y轴移动到安全位置");
            ret = Bottle_YPullOutToSafe(oneDrugRow);
            if (0 == ret) { return 0; }

            //这里面添加判断，下一行还有没有药了，如果没有，打回溶媒
            COneRowStation nextRow = oneLoop.MultyRowStation[row + 1];
            bool nextRowHaveUsedBottle = nextRow.HaveDrug();
            if (true == nextRowHaveUsedBottle)
            {
                SetRunState("下一行还有西林瓶需要抽液");
                bool NeedReback = PumpBack_NeedRebackSolvent(nextRow, pumpbackLoopIndex);//判断需不需要将回抽的回打溶媒袋
                if (true == NeedReback)
                {
                    //注射器的剩余容积，小于西林瓶的容积，则回打溶媒
                    SetRunState("回打到溶媒袋！");
                    int[] validCol_Solvent = mInjectors.GetHadVolumeFlag();
                    ret = PumpBack_SolventInAndPullInjector(SolventRow, validCol_Solvent, pumpbackLoopIndex);
                    if (0 == ret) { return 0; }
                }
            }

            return 1;
        }

        private bool needleInBottleFlag = false;

        //回抽注入空气
        private long PumpBack_InAir(COneRowStation oneRow, int[] validCol, int pumpbackLoopIndex)
        {
            long ret = 0;
            double[] pumpBackInAire = oneRow.GetPumpBackInAire(pumpbackLoopIndex);

            double[] validAireML = GetValidValue(pumpBackInAire, validCol);//要多注入的空气
            int[] inAirSpeed = oneRow.GetPumpBackInAireSpeed(pumpbackLoopIndex);
            if (false == AllValueIsZero(validAireML))
            {
                SetRunState("粉剂：回抽注入空气");
                ret = InAir(oneRow, validCol, validAireML, inAirSpeed);
                if (0 == ret) { return 0; }
                needleInBottleFlag = true;
            }
            else
            {
                needleInBottleFlag = false;
                return 1;
            }
            return 1;
        }

        //回抽的反复多抽
        private long PumpBack_RepetitivePushAndPull(COneRowStation oneRow, int[] validCol, int pumpbackLoopIndex)
        {
            long ret = 0;
            SetRunState("回抽反复多抽");
            //double InjectorResidualMinVolume = oneRow.GetMinResidualVolume(StationColNum);
            int[] outSpeed = oneRow.GetPumpBackRePullOutSpeed(pumpbackLoopIndex);
            int[] inSpeed = oneRow.GetPumpBackRePullInSpeed(pumpbackLoopIndex);
            int[] repullCount = oneRow.GetPumpBackRePullCount(pumpbackLoopIndex);
            double[] volume = oneRow.GetPumpBackRePullVolume(pumpbackLoopIndex);
            double[] waitTime = oneRow.GetPumpBackRePullkWait(pumpbackLoopIndex);
            int maxRepullCount = GetMaxValue(repullCount);
            double maxVolume = GetMaxValue(volume);
            double maxWaitTime = GetMaxValue(waitTime);
            if ((maxRepullCount > 0) && (maxVolume > 0))
            {
                ret = RepetitivePushAndPull(oneRow, validCol, pumpbackLoopIndex, maxRepullCount, volume, inSpeed, outSpeed, maxWaitTime);
                if (0 == ret) { return 0; }
            }

            return 1;
        }

        private bool PumpBack_NeedRebackSolvent(COneRowStation nextRow, int pumpbackLoopIndex)
        {
            SetRunState("下一行还有西林瓶需要抽液");
            bool NeedReback = false;
            double[] pumpbackVolume = nextRow.GetPumpbackVolume(pumpbackLoopIndex);
            double maxPumpbackVolume = GetMaxValue(pumpbackVolume);
            {
                if (maxPumpbackVolume <= DeviceConfig.ShuiZhenMaxML)
                {
                    double[] pumpbackOutVolume = nextRow.GetPumpbackVolume(pumpbackLoopIndex);
                    for (int col = 0; col < StationColNum; col++)
                    {
                        if ((nextRow.RowStations[col].UsedFlag == 1))
                        {
                            if (mInjectors.injectors[col].InjectResidualVolume < pumpbackOutVolume[col])
                            {
                                //注射器的剩余容积小于一个瓶子的回抽容积,？？？？？？需要添加下一行启用标志位判断
                                SetRunState("粉剂回抽：注射器容积不够，需要回打！");
                                NeedReback = true;
                                break;
                            }
                        }
                    }
                }
            }
            return NeedReback;
        }

        private bool NeedRebackByInjectors()
        {
            double[] injectorHadVolume = mInjectors.GetInjectHadUsedVolume();
            bool isZero = AllValueIsZero(injectorHadVolume);
            if (false == isZero)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion 回抽

        #region 其他函数

        //多次循环注入空气
        private List<double[]> GetInAirLoopValue(COneRowStation currentRow, double[] InjectorResidualVolume, double[] airml)
        {
            List<double[]> loopAir = new List<double[]>();
            double[] NeedInAirVolume = airml;
            //获取最大的循环次数
            double v = GetMaxLoopOfOneRow(currentRow, InjectorResidualVolume, NeedInAirVolume);
            //向上取整
            int maxLoopCount = (int)Math.Ceiling(Convert.ToDouble(v));
            //向下取整
            int minLoopCount = (int)Math.Floor(Convert.ToDouble(v));
            //初始化
            InitializeInAireLoopStaion(maxLoopCount, ref loopAir);
            for (int col = 0; col < StationColNum; col++)
            {
                if (currentRow.RowStations[col].UsedFlag == 1)
                {
                    double Col_InjectorResidualVolume = InjectorResidualVolume[col];
                    double Col_NeedInAireVolume = NeedInAirVolume[col];
                    double sub = Col_NeedInAireVolume - Col_InjectorResidualVolume * minLoopCount;
                    if (Col_InjectorResidualVolume == 0)
                    {
                        sub = 0;
                    }
                    if (Col_NeedInAireVolume <= Col_InjectorResidualVolume)
                    {
                        //注射器内的剩余容积 > 需要注入的空气容积
                        loopAir[0][col] = Col_NeedInAireVolume;
                    }
                    else
                    {
                        if (maxLoopCount == minLoopCount)
                        {
                            //说明，两个数可以整除
                            for (int loop = 0; loop < minLoopCount; loop++)
                            {
                                loopAir[loop][col] = Col_InjectorResidualVolume;
                            }
                        }
                        else
                        {
                            for (int loop = 0; loop < maxLoopCount; loop++)
                            {
                                if (loop < minLoopCount)
                                {
                                    loopAir[loop][col] = Col_InjectorResidualVolume;
                                }
                                else
                                {
                                    if (Col_InjectorResidualVolume == 0)
                                    {
                                        loopAir[loop][col] = 0;
                                    }
                                    else
                                    {
                                        loopAir[loop][col] = sub;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return loopAir;
        }

        //
        private CSZ_Loop SZ_GetLoopValue(COneRowStation drugRow)
        {
            double[] OneRow_InjectorResidualVolume = new double[MaxColPointCount];//每个注射器的剩余容积
            double[] OneRow_NeedPullOutVolume = new double[MaxColPointCount];//每行需要抽出的容积
            double[] InjectorResidual = mInjectors.GetInjectResidualVolume();//获取注射器剩余容积
            double[] bottleVolume = drugRow.GetBOTTLE_VOLUME();
            for (int col = 0; col < StationColNum; col++)
            {
                OneRow_InjectorResidualVolume[col] = InjectorResidual[col];
                if (drugRow.RowStations[col].UsedFlag == 1)
                {
                    if (drugRow.RowStations[col].FeiZhengZhiMode == 1)
                    {
                        //非整支
                        OneRow_NeedPullOutVolume[col] = drugRow.RowStations[col].fzz_OutVolume;
                    }
                    else
                    {
                        //整支
                        OneRow_NeedPullOutVolume[col] = bottleVolume[col];
                    }
                }
                else
                {
                    OneRow_NeedPullOutVolume[col] = 0;
                }
            }
            double maxLoopCount = GetMaxLoopOfOneRow(drugRow, OneRow_InjectorResidualVolume, OneRow_NeedPullOutVolume);
            //向下取整
            int a1 = (int)Math.Floor(Convert.ToDouble(maxLoopCount));
            //向上取整
            int b1 = (int)Math.Ceiling(Convert.ToDouble(maxLoopCount));
            CSZ_Loop sZ_Loop = new CSZ_Loop();
            SZ_InitializeLoopStaion(b1, ref sZ_Loop);
            for (int col = 0; col < StationColNum; col++)
            {
                if (drugRow.RowStations[col].UsedFlag == 1)
                {
                    double Col_InjectorResidualVolume = OneRow_InjectorResidualVolume[col];
                    double Col_NeedPullOutVolume = OneRow_NeedPullOutVolume[col];
                    double nextRowResidual = Col_InjectorResidualVolume - Col_NeedPullOutVolume;
                    if (Col_NeedPullOutVolume <= Col_InjectorResidualVolume)
                    {
                        //要抽取的溶媒体积，小于注射器内的剩余容积
                        sZ_Loop.OneRowLoop[0].UsedFlag[col] = 1;
                        sZ_Loop.OneRowLoop[0].OneRowOutVolume[col] = Col_NeedPullOutVolume;
                        if (nextRowResidual <= 0)
                        {
                            //需要回打溶媒
                            sZ_Loop.OneRowLoop[0].NeedBackToSolvent[col] = true;
                        }
                        else
                        {
                            sZ_Loop.OneRowLoop[0].NeedBackToSolvent[col] = false;
                        }
                    }
                    else
                    {
                        //要抽取的容积，大于注射器内的剩余容积
                        //第一次抽取循环，可以抽取的容积，是注射器内的剩余容积
                        double ResidualAfterFirstLoop = Col_NeedPullOutVolume - Col_InjectorResidualVolume;//最后一次循环，需要抽取的容积
                        sZ_Loop.OneRowLoop[0].UsedFlag[col] = 1;
                        sZ_Loop.OneRowLoop[0].OneRowOutVolume[col] = Col_InjectorResidualVolume;
                        sZ_Loop.OneRowLoop[0].NeedBackToSolvent[col] = true;
                        double v2 = ResidualAfterFirstLoop / DeviceConfig.ShuiZhenMaxML;

                        int a = (int)Math.Floor(Convert.ToDouble(v2));
                        //向上取整
                        int b = (int)Math.Ceiling(Convert.ToDouble(v2));
                        if (a == b)
                        {
                            //说明，两个数可以整除,注射器的剩余容积等于，水针的容积
                            for (int I = 0; I < b; I++)
                            {
                                sZ_Loop.OneRowLoop[I + 1].UsedFlag[col] = 1;
                                sZ_Loop.OneRowLoop[I + 1].OneRowOutVolume[col] = DeviceConfig.ShuiZhenMaxML;
                                sZ_Loop.OneRowLoop[I + 1].NeedBackToSolvent[col] = true;
                            }
                        }
                        else
                        {
                            if (a == 0)
                            {
                                //注射器的容积，大于水针的容积，可以一次抽取玩
                                sZ_Loop.OneRowLoop[1].UsedFlag[col] = 1;
                                sZ_Loop.OneRowLoop[1].OneRowOutVolume[col] = ResidualAfterFirstLoop;
                                //添加判断需不要，回打溶媒，只要当前一次可以抽完，切小于注射器的剩余容积，就不需要回打
                                sZ_Loop.OneRowLoop[1].NeedBackToSolvent[col] = false;
                            }
                            else
                            {
                                //第一次循环后，剩下的容积还是大于注射器内的容积，
                                double LastLoop_ResidualVolume = ResidualAfterFirstLoop - DeviceConfig.ShuiZhenMaxML * a;//最后一次循环，需要抽取的容积/体积
                                for (int i = 0; i < b; i++)
                                {
                                    sZ_Loop.OneRowLoop[i + 1].UsedFlag[col] = 1;
                                    if (i < a)
                                    {
                                        sZ_Loop.OneRowLoop[i + 1].OneRowOutVolume[col] = DeviceConfig.ShuiZhenMaxML;
                                        sZ_Loop.OneRowLoop[i + 1].NeedBackToSolvent[col] = true;
                                    }
                                    else
                                    {
                                        sZ_Loop.OneRowLoop[i + 1].OneRowOutVolume[col] = LastLoop_ResidualVolume;
                                        sZ_Loop.OneRowLoop[i + 1].NeedBackToSolvent[col] = false;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return sZ_Loop;
        }

        //获取最大的循环次数
        private double GetMaxLoopOfOneRow(COneRowStation oneRow, double[] InjectorResidualVolume, double[] NeedOutVolume)
        {
            double[] m = new double[8];
            for (int col = 0; col < StationColNum; col++)
            {
                if (oneRow.RowStations[col].UsedFlag == 1)
                {
                    double v1 = 0;
                    if (NeedOutVolume[col] <= InjectorResidualVolume[col])
                    {
                        //要抽取的容积小于注射器的容积，则注射器一次就可以抽完了
                        if (InjectorResidualVolume[col] > 0)
                        {
                            v1 = 1;
                        }
                    }
                    else
                    {
                        //要抽取的容积大于，注射器的剩余容积
                        if (InjectorResidualVolume[col] > 0)
                        {
                            double sub = NeedOutVolume[col] - InjectorResidualVolume[col];
                            v1 = sub / DeviceConfig.ShuiZhenMaxML + 1;
                            // v1=NeedOutVolume[col] / InjectorResidualVolume[col];
                        }
                    }
                    m[col] = v1;
                }
                else
                {
                    m[col] = 0;
                }
            }
            double v = GetMaxValue(m);
            //向下取整
            int a = (int)Math.Floor(Convert.ToDouble(v));
            //向上取整
            int b = (int)Math.Ceiling(Convert.ToDouble(v));
            return v;
        }

        private void SZ_InitializeLoopStaion(int loopcount, ref CSZ_Loop sz_loop)
        {
            for (int loop = 0; loop < loopcount; loop++)
            {
                CSZ_OneRowStation onerow = new CSZ_OneRowStation();
                for (int col = 0; col < StationColNum; col++)
                {
                    CSZ_OneStation oneStation = new CSZ_OneStation();
                    onerow.UsedFlag[col] = 0;
                    onerow.OneRowOutVolume[col] = 0;
                    onerow.NeedBackToSolvent[col] = false;
                }
                sz_loop.OneRowLoop.Add(onerow);
            }
        }

        private void InitializeInAireLoopStaion(int loopcount, ref List<double[]> sz_loop)
        {
            sz_loop.Clear();
            for (int loop = 0; loop < loopcount; loop++)
            {
                double[] onerow = new double[MaxColPointCount];
                for (int col = 0; col < StationColNum; col++)
                {
                    onerow[col] = 0;
                }
                sz_loop.Add(onerow);
            }
        }

        #endregion 其他函数
    }
}